Commit initial
This commit is contained in:
21
server/conf/nginx/nginx.conf
Normal file
21
server/conf/nginx/nginx.conf
Normal file
@ -0,0 +1,21 @@
|
||||
user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
rtmp {
|
||||
server {
|
||||
listen 1935;
|
||||
|
||||
application livecam {
|
||||
live on;
|
||||
record off;
|
||||
on_play http://localhost/client-auth/;
|
||||
on_publish http://localhost/camera-auth/;
|
||||
exec_kill_signal int;
|
||||
exec_push /usr/bin/python /srv/http/projet-l3-info/lib/recorder.py rtmp://localhost/$app/$name $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
server/conf/sql/startBDD.sql
Normal file
79
server/conf/sql/startBDD.sql
Normal file
@ -0,0 +1,79 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 4.1.14
|
||||
-- http://www.phpmyadmin.net
|
||||
--
|
||||
-- Client : 127.0.0.1
|
||||
-- Généré le : Ven 06 Mai 2016 à 16:11
|
||||
-- Version du serveur : 5.6.17
|
||||
-- Version de PHP : 5.5.12
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
|
||||
--
|
||||
-- Base de données : `projetl3`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `camera`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `camera` (
|
||||
`id` varchar(20) NOT NULL,
|
||||
`product_key` varchar(32) CHARACTER SET utf8 NOT NULL,
|
||||
`available` int(1) NOT NULL,
|
||||
`enabled` int(1) NOT NULL,
|
||||
`rtmp_handle` varchar(256) CHARACTER SET utf8 NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `id` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `user`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`login` varchar(255) NOT NULL,
|
||||
`password` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Structure de la table `user_camera`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_camera` (
|
||||
`user_id` int(17) NOT NULL,
|
||||
`camera_id` varchar(20) NOT NULL,
|
||||
`name` varchar(20) NOT NULL,
|
||||
PRIMARY KEY (`user_id`,`camera_id`),
|
||||
KEY `camera_id` (`camera_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Contraintes pour les tables exportées
|
||||
--
|
||||
|
||||
--
|
||||
-- Contraintes pour la table `user_camera`
|
||||
--
|
||||
ALTER TABLE `user_camera`
|
||||
ADD CONSTRAINT `user_camera_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
|
||||
ADD CONSTRAINT `user_camera_ibfk_2` FOREIGN KEY (`camera_id`) REFERENCES `camera` (`id`);
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
7
server/lib/CameraCommander/Camera.py
Normal file
7
server/lib/CameraCommander/Camera.py
Normal file
@ -0,0 +1,7 @@
|
||||
class Camera:
|
||||
def __init__(self, id, product_key, available, enabled, rtmp_handle):
|
||||
self.id = id
|
||||
self.product_key = product_key
|
||||
self.available = available
|
||||
self.enabled = enabled
|
||||
self.rtmp_handle = rtmp_handle
|
||||
33
server/lib/CameraCommander/CameraCommander.py
Normal file
33
server/lib/CameraCommander/CameraCommander.py
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
class CameraCommander:
|
||||
class InvalidStateException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
Cameras = []
|
||||
|
||||
|
||||
def Register(context, camera):
|
||||
for c in CameraCommander.Cameras:
|
||||
if c.camera.id == camera.id:
|
||||
print("[CameraCommander] : Camera ({}) already registered".format(camera.id))
|
||||
raise CameraCommander.InvalidStateException()
|
||||
CameraCommander.Cameras.append(context)
|
||||
print("[CameraCommander] : Camera ({}) registered".format(camera.id))
|
||||
|
||||
|
||||
def GetContext(camera):
|
||||
for c in CameraCommander.Cameras:
|
||||
if c.camera.id == camera.id:
|
||||
return c
|
||||
return None
|
||||
|
||||
|
||||
def IsRegistered(context):
|
||||
return context in CameraCommander.Cameras
|
||||
|
||||
|
||||
def Remove(context):
|
||||
CameraCommander.Cameras.remove(context)
|
||||
print("[CameraCommander] : Camera ({}) unregistered".format(context.camera.id))
|
||||
32
server/lib/CameraCommander/CameraConnection.py
Normal file
32
server/lib/CameraCommander/CameraConnection.py
Normal file
@ -0,0 +1,32 @@
|
||||
import socket
|
||||
|
||||
|
||||
class CameraConnection:
|
||||
def __init__(self, sock, addr):
|
||||
self.sock = sock
|
||||
self.addr = addr[0]
|
||||
self.port = addr[1]
|
||||
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 300)
|
||||
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)
|
||||
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4)
|
||||
|
||||
|
||||
def receive(self):
|
||||
data = b""
|
||||
ret = self.sock.recv(1)
|
||||
while ret and ret != b"\x00":
|
||||
data = data + ret
|
||||
ret = self.sock.recv(1)
|
||||
if not data:
|
||||
return None
|
||||
return data.decode()
|
||||
|
||||
|
||||
def send(self, msg):
|
||||
data = (msg + "\0").encode()
|
||||
return self.sock.send(data) == len(data)
|
||||
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
86
server/lib/CameraCommander/CameraContext.py
Normal file
86
server/lib/CameraCommander/CameraContext.py
Normal file
@ -0,0 +1,86 @@
|
||||
from CameraModel import CameraModel
|
||||
from CameraCommander import CameraCommander
|
||||
from WaitAuthentication import WaitAuthentication
|
||||
from WaitEnabledModeReply import WaitEnabledModeReply
|
||||
from WaitDisabledModeReply import WaitDisabledModeReply
|
||||
from WaitDisconnectedReply import WaitDisconnectedReply
|
||||
from DeadState import DeadState
|
||||
|
||||
|
||||
class CameraContext:
|
||||
class InvalidStateException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def __init__(self, connection):
|
||||
self.camera = None
|
||||
self.connection = connection
|
||||
self.state = WaitAuthentication()
|
||||
|
||||
|
||||
def handle(self):
|
||||
return self.state.handle(self)
|
||||
|
||||
|
||||
def tic(self):
|
||||
self.state.tic(self)
|
||||
|
||||
|
||||
def enable(self, userCommand = None):
|
||||
if not self.camera or not self.connection:
|
||||
raise CameraContext.InvalidStateException()
|
||||
if not self.connection.send("enable"):
|
||||
print("[CameraContext] : Connection lost with camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.close()
|
||||
if userCommand:
|
||||
userCommand.callback(False, "connection_lost")
|
||||
return False
|
||||
print("[CameraContext] : Ask for enabling RTMP streaming on camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.state = WaitEnabledModeReply(userCommand)
|
||||
return True
|
||||
|
||||
|
||||
def disable(self, userCommand = None):
|
||||
if not self.camera or not self.connection:
|
||||
raise CameraContext.InvalidStateException()
|
||||
if not self.connection.send("disable"):
|
||||
print("[CameraContext] : Connection lost with camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.close()
|
||||
if userCommand:
|
||||
userCommand.callback(False, "connection_lost")
|
||||
return False
|
||||
print("[CameraContext] : Ask for disabling RTMP streaming on camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.state = WaitDisabledModeReply(userCommand)
|
||||
return True
|
||||
|
||||
|
||||
def disconnect(self, userCommand = None):
|
||||
if not self.camera or not self.connection:
|
||||
raise CameraContext.InvalidStateException()
|
||||
if not self.connection.send("disconnect"):
|
||||
print("[CameraContext] : Connection lost with camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.close()
|
||||
if userCommand:
|
||||
userCommand.callback(False, "connection_lost")
|
||||
return False
|
||||
print("[CameraContext] : Ask for disconnecting camera ({}) at {}:{}".format(self.camera.id, self.connection.addr, self.connection.port))
|
||||
self.state = WaitDisconnectedReply(userCommand)
|
||||
return True
|
||||
|
||||
|
||||
def close(self):
|
||||
if not self.connection:
|
||||
raise CameraContext.InvalidStateException()
|
||||
if CameraCommander.IsRegistered(self):
|
||||
CameraCommander.Remove(self)
|
||||
if not self.camera:
|
||||
raise CameraContext.InvalidStateException()
|
||||
mdl = CameraModel()
|
||||
self.camera.available = False
|
||||
self.camera.rtmp_handle = ""
|
||||
mdl.update(self.camera)
|
||||
self.camera = None
|
||||
print("[CameraContext] : Close connection with {}:{}".format(self.connection.addr, self.connection.port))
|
||||
self.connection.close()
|
||||
self.connection = None
|
||||
self.state = DeadState()
|
||||
24
server/lib/CameraCommander/CameraModel.py
Normal file
24
server/lib/CameraCommander/CameraModel.py
Normal file
@ -0,0 +1,24 @@
|
||||
import DataBase
|
||||
from Camera import Camera
|
||||
|
||||
|
||||
class CameraModel:
|
||||
def getById(self, id):
|
||||
db = DataBase.GetConnection()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""SELECT * FROM camera WHERE id=%s""", (id,))
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
db.close()
|
||||
if row:
|
||||
return Camera(row[0], row[1], bool(row[2]), bool(row[3]), row[4])
|
||||
return None
|
||||
|
||||
|
||||
def update(self, camera):
|
||||
db = DataBase.GetConnection()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""UPDATE camera SET available=%s, enabled=%s, rtmp_handle=%s WHERE id=%s""", (int(camera.available), int(camera.enabled), camera.rtmp_handle, camera.id))
|
||||
cursor.close()
|
||||
db.commit()
|
||||
db.close()
|
||||
8
server/lib/CameraCommander/DataBase.py
Normal file
8
server/lib/CameraCommander/DataBase.py
Normal file
@ -0,0 +1,8 @@
|
||||
import mysql.connector
|
||||
|
||||
|
||||
def GetConnection():
|
||||
try:
|
||||
return mysql.connector.connect(user = "camplatform_user", password = "lLZwfSLuwye3qW4r", host = "public.lan", database = "camplatform_db")
|
||||
except mysql.connector.Error:
|
||||
return None
|
||||
10
server/lib/CameraCommander/DeadState.py
Normal file
10
server/lib/CameraCommander/DeadState.py
Normal file
@ -0,0 +1,10 @@
|
||||
from WaitState import WaitState
|
||||
|
||||
|
||||
class DeadState(WaitState):
|
||||
def handle(self, context):
|
||||
pass
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
pass
|
||||
5
server/lib/CameraCommander/User.py
Normal file
5
server/lib/CameraCommander/User.py
Normal file
@ -0,0 +1,5 @@
|
||||
class User:
|
||||
def __init__(self, id, login, password):
|
||||
self.id = id
|
||||
self.login = login
|
||||
self.password = password
|
||||
120
server/lib/CameraCommander/UserCommand.py
Normal file
120
server/lib/CameraCommander/UserCommand.py
Normal file
@ -0,0 +1,120 @@
|
||||
from UserModel import UserModel
|
||||
from CameraModel import CameraModel
|
||||
import CameraCommander
|
||||
from WaitActivity import WaitActivity
|
||||
|
||||
|
||||
class UserCommand:
|
||||
class InvalidStateException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def __init__(self, sock, addr):
|
||||
self.sock = sock
|
||||
self.addr = addr[0]
|
||||
self.port = addr[1]
|
||||
|
||||
|
||||
def receive(self):
|
||||
data = b""
|
||||
ret = self.sock.recv(1)
|
||||
while ret and ret != b"\x00":
|
||||
data = data + ret
|
||||
ret = self.sock.recv(1)
|
||||
if not data:
|
||||
return None
|
||||
return data.decode()
|
||||
|
||||
|
||||
def send(self, msg):
|
||||
data = (msg + "\0").encode()
|
||||
return self.sock.send(data) == len(data)
|
||||
|
||||
|
||||
def close(self):
|
||||
print("[UserCommand] : Closing connection with {}:{}".format(self.addr, self.port))
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
self.addr = None
|
||||
self.port = None
|
||||
|
||||
|
||||
def callback(self, result, error_msg = None):
|
||||
print("[UserCommand] : Send reply to {}:{}".format(self.addr, self.port))
|
||||
if result:
|
||||
self.send("ok")
|
||||
elif error_msg:
|
||||
self.send("error:" + error_msg)
|
||||
else:
|
||||
self.send("error")
|
||||
self.close()
|
||||
|
||||
|
||||
def execute(self):
|
||||
if not self.sock:
|
||||
raise UserCommand.InvalidStateException()
|
||||
data = self.receive()
|
||||
if not data:
|
||||
print("[UserCommand] : Connection lost with {}:{}".format(self.addr, self.port))
|
||||
self.close()
|
||||
return
|
||||
|
||||
words = data.split(":")
|
||||
if len(words) != 4:
|
||||
print("[UserCommand] : Error from {}:{}, invalid data".format(self.addr, self.port))
|
||||
self.send("error:invalid_data")
|
||||
self.close()
|
||||
return
|
||||
|
||||
userMdl = UserModel()
|
||||
user = userMdl.getByLogin(words[0])
|
||||
if not user:
|
||||
print("[UserCommand] : Error from {}:{}, invalid username".format(self.addr, self.port))
|
||||
self.send("error:invalid_username")
|
||||
self.close()
|
||||
return
|
||||
|
||||
if user.password != words[1]:
|
||||
print("[UserCommand] : Error from {}:{}, invalid password for user ({})".format(self.addr, self.port, user.login))
|
||||
self.send("error:invalid_password")
|
||||
self.close()
|
||||
return
|
||||
|
||||
camMdl = CameraModel()
|
||||
camera = camMdl.getById(words[3])
|
||||
if not camera:
|
||||
print("[UserCommand] : Error from user ({}) at {}:{}, invalid camera's serial number".format(user.login, self.addr, self.port))
|
||||
self.send("error:invalid_camera_id")
|
||||
self.close()
|
||||
return
|
||||
|
||||
if not userMdl.haveCamera(user, camera):
|
||||
print("[UserCommand] : User ({}) at {}:{} is not allowed to command camera ({})".format(user.login, self.addr, self.port, camera.id))
|
||||
self.send("error:not_authorized")
|
||||
self.close()
|
||||
return
|
||||
|
||||
context = CameraCommander.CameraCommander.GetContext(camera)
|
||||
if not context:
|
||||
print("[UserCommand] : Error from user ({}) at {}:{}, camera ({}) is not registered".format(user.login, self.addr, self.port, camera.id))
|
||||
self.send("error:camera_not_registered")
|
||||
self.close()
|
||||
return
|
||||
|
||||
if not isinstance(context.state, WaitActivity):
|
||||
print("[UserCommand] : Error from user ({}) at {}:{}, camera ({}) is busy".format(user.login, self.addr, self.port, camera.id))
|
||||
self.send("error:camera_busy")
|
||||
self.close()
|
||||
return
|
||||
|
||||
if words[2] == "enable":
|
||||
context.enable(self)
|
||||
elif words[2] == "disable":
|
||||
context.disable(self)
|
||||
elif words[2] == "disconnect":
|
||||
context.disconnect(self)
|
||||
else:
|
||||
print("[UserCommand] : Error from user ({}) at {}:{}, invalid command".format(user.login, self.addr, self.port))
|
||||
self.send("error:invalid_command")
|
||||
self.close()
|
||||
return
|
||||
28
server/lib/CameraCommander/UserModel.py
Normal file
28
server/lib/CameraCommander/UserModel.py
Normal file
@ -0,0 +1,28 @@
|
||||
import DataBase
|
||||
from User import User
|
||||
|
||||
|
||||
class UserModel:
|
||||
def getByLogin(self, login):
|
||||
db = DataBase.GetConnection()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""SELECT * FROM user WHERE login=%s""", (login,))
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
db.close()
|
||||
if row:
|
||||
return User(row[0], row[1], row[2])
|
||||
return None
|
||||
|
||||
|
||||
def haveCamera(self, user, camera):
|
||||
db = DataBase.GetConnection()
|
||||
cursor = db.cursor()
|
||||
cursor.execute("""SELECT * FROM user_camera WHERE user_id=%s AND camera_id=%s""", (user.id, camera.id))
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
db.close()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
14
server/lib/CameraCommander/WaitActivity.py
Normal file
14
server/lib/CameraCommander/WaitActivity.py
Normal file
@ -0,0 +1,14 @@
|
||||
from WaitState import WaitState
|
||||
from CameraCommander import CameraCommander
|
||||
|
||||
|
||||
class WaitActivity(WaitState):
|
||||
def handle(self, context):
|
||||
data = self.waitMsg(context)
|
||||
if data:
|
||||
print("[WaitActivity] : Error({}) from camera ({}) at {}:{}".format(data, context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
pass
|
||||
55
server/lib/CameraCommander/WaitAuthentication.py
Normal file
55
server/lib/CameraCommander/WaitAuthentication.py
Normal file
@ -0,0 +1,55 @@
|
||||
import random
|
||||
|
||||
from CameraCommander import CameraCommander
|
||||
from CameraModel import CameraModel
|
||||
from WaitState import WaitState
|
||||
from WaitActivity import WaitActivity
|
||||
import CameraContext
|
||||
|
||||
|
||||
class WaitAuthentication(WaitState):
|
||||
def handle(self, context):
|
||||
data = self.waitMsg(context)
|
||||
if not data:
|
||||
return
|
||||
words = data.split(":")
|
||||
if len(words) != 2:
|
||||
print("[WaitAuthentication] : Invalid data from camera at {}:{}".format(context.connection.addr, context.connection.port))
|
||||
context.connection.send("invalid_data")
|
||||
context.close()
|
||||
return
|
||||
|
||||
mdl = CameraModel()
|
||||
camera = mdl.getById(words[0])
|
||||
if not camera or camera.product_key != words[1]:
|
||||
print("[WaitAuthentication] : Authentication failed for camera at {}:{}".format(context.connection.addr, context.connection.port))
|
||||
context.connection.send("refused")
|
||||
context.close()
|
||||
return
|
||||
|
||||
try:
|
||||
CameraCommander.Register(context, camera)
|
||||
except CameraCommander.InvalidStateException:
|
||||
context.connection.send("refused")
|
||||
context.close()
|
||||
return
|
||||
|
||||
context.camera = camera
|
||||
print("[WaitAuthentication] : Camera at {}:{} successfully authenticated as ({})".format(context.connection.addr, context.connection.port, context.camera.id))
|
||||
|
||||
context.camera.available = True
|
||||
context.camera.rtmp_handle = hex(hash(random.random()))[2:]
|
||||
mdl.update(context.camera)
|
||||
if not context.connection.send("accepted:{}".format(context.camera.rtmp_handle)):
|
||||
print("[WaitAuthentication] : Connection lost with camera ({}) at {}:{}".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
return
|
||||
|
||||
if context.camera.enabled:
|
||||
context.enable()
|
||||
return
|
||||
context.state = WaitActivity()
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
pass
|
||||
40
server/lib/CameraCommander/WaitDisabledModeReply.py
Normal file
40
server/lib/CameraCommander/WaitDisabledModeReply.py
Normal file
@ -0,0 +1,40 @@
|
||||
import time
|
||||
|
||||
from CameraModel import CameraModel
|
||||
from WaitState import WaitState
|
||||
from WaitActivity import WaitActivity
|
||||
|
||||
|
||||
class WaitDisabledModeReply(WaitState):
|
||||
def __init__(self, userCommand):
|
||||
self.userCommand = userCommand
|
||||
self.initTime = time.time()
|
||||
|
||||
|
||||
def handle(self, context):
|
||||
data = self.waitMsg(context)
|
||||
if not data:
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "connection_lost")
|
||||
return
|
||||
if data == "disabled":
|
||||
print("[WaitDisabledModeReply] : Camera ({}) at {}:{} successfully disabled".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.camera.enabled = False
|
||||
mdl = CameraModel()
|
||||
mdl.update(context.camera)
|
||||
context.state = WaitActivity()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(True)
|
||||
else:
|
||||
print("[WaitDisabledModeReply] : Error({}) from camera ({}) at {}:{}".format(data, context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, data)
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
if time.time() - self.initTime > 10:
|
||||
print("[WaitDisabledModeReply] : Timeout exeeded for camera ({}) at {}:{}".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "timeout")
|
||||
35
server/lib/CameraCommander/WaitDisconnectedReply.py
Normal file
35
server/lib/CameraCommander/WaitDisconnectedReply.py
Normal file
@ -0,0 +1,35 @@
|
||||
import time
|
||||
|
||||
from WaitState import WaitState
|
||||
|
||||
|
||||
class WaitDisconnectedReply(WaitState):
|
||||
def __init__(self, userCommand):
|
||||
self.userCommand = userCommand
|
||||
self.initTime = time.time()
|
||||
|
||||
|
||||
def handle(self, context):
|
||||
data = self.waitMsg(context)
|
||||
if not data:
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "connection_lost")
|
||||
return
|
||||
if data == "disconnected":
|
||||
print("[CameraContext] : Camera ({}) at {}:{} successfully disconnected".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(True)
|
||||
else:
|
||||
print("[WaitDisconnectedReply] : Error({}) from camera ({}) at {}:{}".format(data, context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, data)
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
if time.time() - self.initTime > 10:
|
||||
print("[WaitEnabledModeReply] : Timeout exeeded for camera ({}) at {}:{}".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "timeout")
|
||||
40
server/lib/CameraCommander/WaitEnabledModeReply.py
Normal file
40
server/lib/CameraCommander/WaitEnabledModeReply.py
Normal file
@ -0,0 +1,40 @@
|
||||
import time
|
||||
|
||||
from CameraModel import CameraModel
|
||||
from WaitState import WaitState
|
||||
from WaitActivity import WaitActivity
|
||||
|
||||
|
||||
class WaitEnabledModeReply(WaitState):
|
||||
def __init__(self, userCommand):
|
||||
self.userCommand = userCommand
|
||||
self.initTime = time.time()
|
||||
|
||||
|
||||
def handle(self, context):
|
||||
data = self.waitMsg(context)
|
||||
if not data:
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "connection_lost")
|
||||
return
|
||||
if data == "enabled":
|
||||
print("[WaitEnabledModeReply] : Camera ({}) at {}:{} successfully enabled".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.camera.enabled = True
|
||||
mdl = CameraModel()
|
||||
mdl.update(context.camera)
|
||||
context.state = WaitActivity()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(True)
|
||||
else:
|
||||
print("[WaitEnabledModeReply] : Error({}) from camera ({}) at {}:{}".format(data, context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, data)
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
if time.time() - self.initTime > 10:
|
||||
print("[WaitEnabledModeReply] : Timeout exeeded for camera ({}) at {}:{}".format(context.camera.id, context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
if self.userCommand:
|
||||
self.userCommand.callback(False, "timeout")
|
||||
17
server/lib/CameraCommander/WaitState.py
Normal file
17
server/lib/CameraCommander/WaitState.py
Normal file
@ -0,0 +1,17 @@
|
||||
class WaitState:
|
||||
def waitMsg(self, context):
|
||||
data = context.connection.receive()
|
||||
if not data:
|
||||
print("[WaitState] : Connection lost with camera at {}:{}".format(context.connection.addr, context.connection.port))
|
||||
context.close()
|
||||
return None
|
||||
else:
|
||||
return data
|
||||
|
||||
|
||||
def handle(self, context):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def tic(self, context):
|
||||
raise NotImplementedError()
|
||||
102
server/lib/CameraCommander/main.py
Normal file
102
server/lib/CameraCommander/main.py
Normal file
@ -0,0 +1,102 @@
|
||||
import socket
|
||||
import select
|
||||
import signal
|
||||
|
||||
from CameraContext import CameraContext
|
||||
from UserCommand import UserCommand
|
||||
from CameraConnection import CameraConnection
|
||||
from CameraCommander import CameraCommander
|
||||
from WaitActivity import WaitActivity
|
||||
|
||||
|
||||
def on_sigint(signal, frame):
|
||||
global server_enabled
|
||||
server_enabled = False
|
||||
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
|
||||
server_enabled = True
|
||||
signal.signal(signal.SIGINT, on_sigint)
|
||||
connected_cameras = []
|
||||
connected_users = []
|
||||
|
||||
cam_listener_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
cam_listener_sock.bind(("", 41551))
|
||||
cam_listener_sock.listen(5)
|
||||
|
||||
cmd_listener_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
cmd_listener_sock.bind(("", 40550))
|
||||
cmd_listener_sock.listen(5)
|
||||
|
||||
|
||||
print("[Main] : Ready")
|
||||
|
||||
while server_enabled or len(CameraCommander.Cameras) > 0:
|
||||
if server_enabled:
|
||||
conn_list, wlist, xlist = select.select([cam_listener_sock, cmd_listener_sock], [], [], 0.05)
|
||||
if cam_listener_sock in conn_list:
|
||||
cam_sock, cam_addr = cam_listener_sock.accept()
|
||||
connected_cameras.append(CameraContext(CameraConnection(cam_sock, cam_addr)))
|
||||
elif cmd_listener_sock in conn_list:
|
||||
user_sock, user_addr = cmd_listener_sock.accept()
|
||||
connected_users.append(UserCommand(user_sock, user_addr))
|
||||
|
||||
new_connected_users = []
|
||||
for userCommand in connected_users:
|
||||
if userCommand.sock:
|
||||
new_connected_users.append(userCommand)
|
||||
connected_users = new_connected_users
|
||||
|
||||
user_sock_list = [userCommand.sock for userCommand in connected_users]
|
||||
|
||||
if server_enabled:
|
||||
sock_read_list, wlist, xlist = select.select(user_sock_list, [], [], 0.05)
|
||||
for user_sock in sock_read_list:
|
||||
for userCommand in connected_users:
|
||||
if user_sock == userCommand.sock:
|
||||
userCommand.execute()
|
||||
|
||||
new_connected_cameras = []
|
||||
for context in connected_cameras:
|
||||
if context.connection:
|
||||
new_connected_cameras.append(context)
|
||||
connected_cameras = new_connected_cameras
|
||||
|
||||
if not server_enabled:
|
||||
for context in CameraCommander.Cameras:
|
||||
if isinstance(context.state, WaitActivity):
|
||||
try:
|
||||
context.disconnect()
|
||||
except CameraContext.TransmissionErrorException:
|
||||
context.close()
|
||||
|
||||
cam_sock_list = [context.connection.sock for context in connected_cameras]
|
||||
|
||||
sock_read_list, wlist, xlist = select.select(cam_sock_list, [], [], 0.05)
|
||||
for cam_sock in sock_read_list:
|
||||
for context in connected_cameras:
|
||||
if cam_sock == context.connection.sock:
|
||||
context.handle()
|
||||
|
||||
for context in connected_cameras:
|
||||
context.tic()
|
||||
|
||||
|
||||
for context in connected_cameras:
|
||||
if context.connection:
|
||||
context.close()
|
||||
|
||||
for userCommand in connected_users:
|
||||
if userCommand.sock:
|
||||
userCommand.close()
|
||||
|
||||
cmd_listener_sock.shutdown(socket.SHUT_RDWR)
|
||||
cmd_listener_sock.close()
|
||||
|
||||
cam_listener_sock.shutdown(socket.SHUT_RDWR)
|
||||
cam_listener_sock.close()
|
||||
|
||||
print("[Main] : Bye !!")
|
||||
73
server/lib/recorder.py
Executable file
73
server/lib/recorder.py
Executable file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import shutil
|
||||
import re
|
||||
import time
|
||||
|
||||
|
||||
def on_term(signum, frame):
|
||||
global ffmpeg
|
||||
global record_enabled
|
||||
record_enabled = False
|
||||
if ffmpeg != None and ffmpeg.poll() == None:
|
||||
ffmpeg.terminate()
|
||||
try:
|
||||
os.remove(os.path.join(record_path, "current.mp4"))
|
||||
except:
|
||||
pass
|
||||
sys.exit(0)
|
||||
elif ffmpeg == None:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
sys.stderr.write("Error : Bad arguments count\n")
|
||||
sys.exit(1)
|
||||
|
||||
ffmpeg = None
|
||||
record_enabled = True
|
||||
rtmp_link = sys.argv[1] + "?login=root&password=99c9bef14824f6a9b7e6ee4229660827a4a4c751"
|
||||
stream_name = sys.argv[2]
|
||||
|
||||
fragment_time = 3600
|
||||
fragment_max_count = 48
|
||||
|
||||
record_path = os.path.join(os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), "../webplatform/www/Content/records")), stream_name)
|
||||
|
||||
if not os.path.exists(record_path):
|
||||
try:
|
||||
os.mkdir(record_path)
|
||||
except OSError:
|
||||
sys.stderr.write("Error : Unable to create the record directory\n")
|
||||
sys.exit(2)
|
||||
|
||||
signal.signal(signal.SIGINT, on_term)
|
||||
|
||||
while record_enabled:
|
||||
files = os.listdir(record_path)
|
||||
|
||||
for filename in files:
|
||||
filepath = os.path.join(record_path, filename)
|
||||
if os.path.isfile(filepath):
|
||||
match = re.search("^([0-9]|[1-9][0-9]*)_([0-9]|[1-9][0-9]*)\.mp4$", filename)
|
||||
if match:
|
||||
if (int(time.time()) - int(match.group(1))) / fragment_time > fragment_max_count:
|
||||
try:
|
||||
os.remove(filepath)
|
||||
except OSError:
|
||||
sys.stderr.write("Error : Unable to delete video backup file\n")
|
||||
sys.exit(3)
|
||||
|
||||
start_time = str(int(time.time()))
|
||||
ffmpeg = subprocess.Popen(["/usr/bin/ffmpeg", "-re", "-y", "-i", rtmp_link, "-an", "-vcodec", "copy", "-movflags", "faststart", "-f", "mp4", "-t", str(fragment_time), os.path.join(record_path, "current.mp4")])
|
||||
ffmpeg.wait()
|
||||
try:
|
||||
os.rename(os.path.join(record_path, "current.mp4"), os.path.join(record_path, "{}_{}.mp4".format(start_time, str(int(time.time())))))
|
||||
except OSError:
|
||||
sys.stderr.write("Error : Unable to rename the current video backup file\n")
|
||||
sys.exit(4)
|
||||
ffmpeg = None
|
||||
10
server/webplatform/apps/CameraMonitor/Config/config.ini
Normal file
10
server/webplatform/apps/CameraMonitor/Config/config.ini
Normal file
@ -0,0 +1,10 @@
|
||||
;Configuration
|
||||
|
||||
[Installation]
|
||||
root = /
|
||||
host = 'cam.wildsparksoftware.com'
|
||||
|
||||
[BD]
|
||||
dsn = 'mysql:host=localhost;dbname=projetl3;charset=utf8'
|
||||
login = root
|
||||
mdp =
|
||||
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Controller/ControllerSecureUserCam.php';
|
||||
require_once $GLOBALS['app_path'].'Model/ModelCamera.php';
|
||||
require_once $GLOBALS['app_path'].'Model/ModelUser.php';
|
||||
require_once $GLOBALS['app_path'].'Model/Entity/Camera.php';
|
||||
|
||||
|
||||
|
||||
class ControllerCamera extends ControllerSecureUserCam {
|
||||
|
||||
public function index()
|
||||
{
|
||||
$modelUser = new ModelUser();
|
||||
$user = $modelUser->getUserById($this->request->getSession()->getAttribute('user_id'));
|
||||
$modelCamera = new ModelCamera();
|
||||
$camera = $modelCamera->getCamera($this->request->getParameter('id'),$this->request->getSession()->getAttribute('user_id'));
|
||||
$headScript = '<script src="jwplayer/jwplayer.js"></script><script>jwplayer.key="xEPI8DEypoE2gSBetC0/Vecoos0JKOx8WLKNMw==";</script>';
|
||||
$this->generateView(array('camera' => $camera, 'headScript' => $headScript, 'user'=> $user));
|
||||
}
|
||||
|
||||
public function swapState()
|
||||
{
|
||||
$whereController = "default";
|
||||
$whereAction = null;
|
||||
if($this->request->existParameter('whereController'))
|
||||
$whereController = $this->request->getParameter('whereController');
|
||||
if($this->request->existParameter('whereAction'))
|
||||
$whereAction = $this->request->getParameter('whereAction');
|
||||
|
||||
if($this->request->existParameter('swap'))
|
||||
{
|
||||
$command = null;
|
||||
$modelUser = new ModelUser();
|
||||
$modelCamera = new ModelCamera();
|
||||
$camera = $modelCamera->getCamera($this->request->getParameter('id'),$this->request->getSession()->getAttribute('user_id'));
|
||||
$login = $this->request->getSession()->getAttribute('login');
|
||||
$password = $modelUser->getUserById($this->request->getSession()->getAttribute('user_id'))->getPassword();
|
||||
$swap = $this->request->getParameter('swap');
|
||||
|
||||
if($swap == 'enable' && $camera->getEnabled() == false)
|
||||
$command = "enable";
|
||||
else
|
||||
if($swap == 'disable' && $camera->getEnabled() == true)
|
||||
$command = 'disable';
|
||||
if($command != null)
|
||||
$this->sendCommand($login,$password,$camera->getId(),$command);
|
||||
}
|
||||
$this->redirect($whereController,$whereAction);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$modelUser = new ModelUser();
|
||||
$modelUser->deleteCam($this->request->getSession()->getAttribute('user_id'),$this->request->getParameter('id'));
|
||||
$this->redirect('default','settings');
|
||||
}
|
||||
|
||||
private function sendCommand($login,$password,$camera_id,$command)
|
||||
{
|
||||
$s = socket_create(AF_INET,SOCK_STREAM,0);
|
||||
if($s == false)
|
||||
throw new Exception("Creation de socket echoue");
|
||||
$addr = gethostbyname(Configuration::get('host'));
|
||||
if($addr == Configuration::get('host'))
|
||||
{
|
||||
socket_close($s);
|
||||
throw new Exception("Recuperation IP impossible ");
|
||||
}
|
||||
$result = socket_connect($s,$addr,40550);
|
||||
if($result == false)
|
||||
{
|
||||
socket_close($s);
|
||||
throw new Exception("Connection socket échoue");
|
||||
}
|
||||
$str = $login.":".$password.":".$command.":".$camera_id; //Command = enable|disable|disconnect
|
||||
$buf = $str."\0";
|
||||
$size = socket_write($s,$buf,strlen($str)+1);
|
||||
if($size != strlen($buf))
|
||||
{
|
||||
socket_close($s);
|
||||
throw new Exception("Ecriture dans la socket impossible");
|
||||
}
|
||||
$data = "";
|
||||
$ret = socket_recv($s, $data, 1, MSG_WAITALL);
|
||||
while($ret == 1 && $data != "\0")
|
||||
{
|
||||
$buf .= $data;
|
||||
$data = "";
|
||||
$ret = socket_recv($s, $data, 1, MSG_WAITALL);
|
||||
}
|
||||
|
||||
if($ret != 1 && strlen($buf) == 0)
|
||||
{
|
||||
socket_close($s);
|
||||
throw new Exception('Erreur rien à lire dans la socket');
|
||||
}
|
||||
|
||||
socket_close($s);
|
||||
}
|
||||
|
||||
public function delayed()
|
||||
{
|
||||
$videos = array();
|
||||
$records_path = "Content/records/".$this->request->getParameter("id");
|
||||
if(file_exists($records_path))
|
||||
{
|
||||
$files = scandir($records_path);
|
||||
if($files != false)
|
||||
{
|
||||
$i = 0;
|
||||
foreach($files as $file)
|
||||
{
|
||||
$path = $records_path."/".$file;
|
||||
|
||||
if(is_file($path))
|
||||
{
|
||||
$regex_results = array();
|
||||
if(preg_match("/^([0-9]|[1-9][0-9]*)_([0-9]|[1-9][0-9]*)\.mp4$/",$file,$regex_results) == 1)
|
||||
{
|
||||
$videos[$i]["path"] = $path;
|
||||
$videos[$i]["begin"] = date('j/n/Y H:i:s',$regex_results[1]);
|
||||
$videos[$i]["end"] = date('j/n/Y H:i:s',$regex_results[2]);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
$headScript = '<script src="jwplayer/jwplayer.js"></script><script>jwplayer.key="xEPI8DEypoE2gSBetC0/Vecoos0JKOx8WLKNMw==";</script>';
|
||||
$this->generateView(array('videos' => $videos, 'headScript' => $headScript));
|
||||
}
|
||||
else
|
||||
throw new Exception("Fichier '".$records_path."' inconnue");
|
||||
}
|
||||
else
|
||||
throw new Exception("Dossier '".$records_path."' inconnue");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
require_once $GLOBALS['app_path'].'Framework/Controller.php';
|
||||
require_once $GLOBALS['app_path'].'Model/ModelUser.php';
|
||||
|
||||
class ControllerConnexion extends Controller
|
||||
{
|
||||
private $modelUser;
|
||||
public function __construct()
|
||||
{
|
||||
$this->modelUser = new ModelUser();
|
||||
}
|
||||
public function index()
|
||||
{
|
||||
$this->generateView();
|
||||
}
|
||||
public function logOn()
|
||||
{
|
||||
if ($this->request->existParameter("login") && $this->request->existParameter("password")) {
|
||||
$login = $this->request->getParameter("login");
|
||||
$password = sha1($this->request->getParameter("password"));
|
||||
if ($this->modelUser->exist($login, $password))
|
||||
{
|
||||
$user = $this->modelUser->getUser($login, $password);
|
||||
$this->request->getSession()->setAttribute("user_id",
|
||||
$user->getId());
|
||||
$this->request->getSession()->setAttribute("login",
|
||||
$user->getLogin());
|
||||
|
||||
if($login == "root")
|
||||
$this->redirect('default','admin');
|
||||
else
|
||||
$this->redirect("default");
|
||||
}
|
||||
else
|
||||
$this->generateView(array('msgError' => 'Login ou mot de passe incorrects'),
|
||||
"index");
|
||||
}
|
||||
else
|
||||
throw new Exception("Action impossible : login ou mot de passe non défini");
|
||||
}
|
||||
|
||||
public function registration()
|
||||
{
|
||||
$this->generateView();
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
if ($this->request->existParameter("login") && $this->request->existParameter("password") && $this->request->existParameter("passwordBis")) {
|
||||
$login = $this->request->getParameter("login");
|
||||
$password = sha1($this->request->getParameter("password"));
|
||||
$passwordBis = sha1($this->request->getParameter("passwordBis"));
|
||||
if ($password == $passwordBis) {
|
||||
if(!$this->modelUser->exist($login,$password))
|
||||
{
|
||||
$this->modelUser->addUser($login, $password);
|
||||
$this->redirect("default");
|
||||
}
|
||||
else
|
||||
$this->generateView(array('msgError' => 'Utilisateur déja existant'),
|
||||
"registration");
|
||||
}
|
||||
else
|
||||
$this->generateView(array('msgError' => 'Les mots de passes doivent être identiques'),
|
||||
"registration");
|
||||
}
|
||||
else
|
||||
throw new Exception("Action impossible : login ou mot de passe non défini");
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
{
|
||||
$this->request->getSession()->destruct();
|
||||
$this->redirect("connexion");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Controller/ControllerSecure.php';
|
||||
require_once $GLOBALS['app_path'].'Model/ModelCamera.php';
|
||||
require_once $GLOBALS['app_path'].'Model/Entity/Camera.php';
|
||||
require_once $GLOBALS['app_path'].'Model/ModelUser.php';
|
||||
|
||||
|
||||
|
||||
|
||||
class ControllerDefault extends ControllerSecure {
|
||||
|
||||
public function index()
|
||||
{
|
||||
$modelCamera = new ModelCamera();
|
||||
$cameras = $modelCamera->getAllCameraByUser($this->request->getSession()->getAttribute('user_id'));
|
||||
$this->generateView(array('cameras' => $cameras));
|
||||
}
|
||||
|
||||
public function settings()
|
||||
{
|
||||
$modelCamera = new ModelCamera();
|
||||
$modelUser = new ModelUser();
|
||||
$user_id = $this->request->getSession()->getAttribute('user_id');
|
||||
$user = $modelUser->getUserById($user_id);
|
||||
$cameras = $modelCamera->getAllCameraByUser($user_id);
|
||||
$this->generateView(array('cameras' => $cameras, 'user' => $user));
|
||||
}
|
||||
|
||||
public function updateLogin()
|
||||
{
|
||||
$messageInfo = "";
|
||||
$modelUser = new ModelUser();
|
||||
$modelCamera = new ModelCamera();
|
||||
$user_id = $this->request->getSession()->getAttribute('user_id');
|
||||
$user = $modelUser->getUserById($user_id);
|
||||
$cameras = $modelCamera->getAllCameraByUser($user_id);
|
||||
|
||||
if($this->request->existParameter('login'))
|
||||
{
|
||||
$login = $this->request->getParameter('login');
|
||||
if($user->getLogin() != $login)
|
||||
{
|
||||
if(!$modelUser->exist($login, $user->getPassword()))
|
||||
{
|
||||
$modelUser->update($user->getId(),$login,$user->getPassword());
|
||||
$messageInfo = "Modification effectué";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Ce login existe déja";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Ce Login est déja le vôtre";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Login manquant";
|
||||
|
||||
$this->generateView(array('cameras' => $cameras, 'user' => $user, 'messageInfo' => $messageInfo ),'settings');
|
||||
}
|
||||
|
||||
public function updatePassword()
|
||||
{
|
||||
$messageInfo = "";
|
||||
$modelUser = new ModelUser();
|
||||
$modelCamera = new ModelCamera();
|
||||
$user_id = $this->request->getSession()->getAttribute('user_id');
|
||||
$user = $modelUser->getUserById($user_id);
|
||||
$cameras = $modelCamera->getAllCameraByUser($user_id);
|
||||
|
||||
if($this->request->existParameter('password') && $this->request->existParameter('passwordBis'))
|
||||
{
|
||||
$password = $this->request->getParameter('password');
|
||||
$passwordBis = $this->request->getParameter('passwordBis');
|
||||
if($password == $passwordBis)
|
||||
{
|
||||
if ($user->getPassword() != $password)
|
||||
{
|
||||
$modelUser->update($user->getId(), $user->getLogin(), $password);
|
||||
$messageInfo = "Modification effectué";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Ce mot de passe est déja le vôtre";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Les deux mot de passe doivent être les mêmes";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Les deux champs mot de passe doivent être remplies";
|
||||
|
||||
$this->generateView(array('cameras' => $cameras, 'user' => $user, 'messageInfo' => $messageInfo ),'settings');
|
||||
}
|
||||
|
||||
public function addCam()
|
||||
{
|
||||
$messageInfo = "";
|
||||
$modelUser = new ModelUser();
|
||||
$modelCamera = new ModelCamera();
|
||||
$user_id = $this->request->getSession()->getAttribute('user_id');
|
||||
$user = $modelUser->getUserById($user_id);
|
||||
|
||||
if($this->request->existParameter('name') && $this->request->existParameter('camera_id'))
|
||||
{
|
||||
$name = $this->request->getParameter('name');
|
||||
$camera_id = $this->request->getParameter('camera_id');
|
||||
if($modelCamera->exist($camera_id))
|
||||
{
|
||||
if (!$modelUser->haveCam($user->getId(), $camera_id))
|
||||
{
|
||||
$modelUser->addCam($user->getId(), $camera_id, $name);
|
||||
$messageInfo = "Modification effectué";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Vous avez déja accès à cette caméra";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Le numéro de série ne correspond à aucune caméra";
|
||||
}
|
||||
else
|
||||
$messageInfo = "Les champs name et numéro de série doivent être remplies";
|
||||
|
||||
$cameras = $modelCamera->getAllCameraByUser($user_id);
|
||||
|
||||
$this->generateView(array('cameras' => $cameras, 'user' => $user, 'messageInfo' => $messageInfo ),'settings');
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
if($this->request->getSession()->getAttribute('login') == "root")
|
||||
{
|
||||
$this->generateView();
|
||||
}
|
||||
else
|
||||
throw new Exception('Vous n\'avez pas accès à cette page');
|
||||
}
|
||||
|
||||
public function addCamAdmin()
|
||||
{
|
||||
if($this->request->getSession()->getAttribute('login') == "root")
|
||||
{
|
||||
$modelCamera = new ModelCamera();
|
||||
$id = uniqid("",false).rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9);
|
||||
$product_key = sha1(strval(rand()));
|
||||
$modelCamera->addCamera($id,$product_key,0,0,"");
|
||||
$this->generateView(array("id"=>$id, "product_key"=>$product_key),"admin");
|
||||
}
|
||||
else
|
||||
throw new Exception('Vous n\'avez pas accès à cette page');
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
require_once $GLOBALS['app_path'].'Framework/Controller.php';
|
||||
|
||||
abstract class ControllerSecure extends Controller
|
||||
{
|
||||
public function executeAction($action)
|
||||
{
|
||||
if ($this->request->getSession()->existAttribute("user_id")) {
|
||||
parent::executeAction($action);
|
||||
}
|
||||
else {
|
||||
$this->redirect("connexion");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
require_once $GLOBALS['app_path'].'Framework/Controller.php';
|
||||
|
||||
abstract class ControllerSecureUserCam extends Controller
|
||||
{
|
||||
public function executeAction($action)
|
||||
{
|
||||
if ($this->request->getSession()->existAttribute("user_id"))
|
||||
{
|
||||
$user_id = $this->request->getSession()->getAttribute("user_id");
|
||||
if($this->request->existParameter('id'))
|
||||
{
|
||||
$camera_id = $this->request->getParameter('id');
|
||||
$modelCamera = new ModelCamera();
|
||||
if($modelCamera->userCanAccessCam($user_id,$camera_id))
|
||||
parent::executeAction($action);
|
||||
else
|
||||
throw new Exception('Vous n\'avez pas accès à cette caméra');
|
||||
}
|
||||
else
|
||||
throw new Exception('Id caméra non spécifié');
|
||||
}
|
||||
else {
|
||||
$this->redirect("connexion");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
class Configuration {
|
||||
|
||||
private static $parameters;
|
||||
|
||||
public static function get($nom, $default = null) {
|
||||
if (isset(self::getParameters()[$nom])) {
|
||||
$value = self::getParameters()[$nom];
|
||||
}
|
||||
else {
|
||||
$value = $default;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
private static function getParameters() {
|
||||
if (self::$parameters == null) {
|
||||
$pathFile = $GLOBALS['app_path']."Config/config.ini";
|
||||
|
||||
if (!file_exists($pathFile)) {
|
||||
throw new Exception("Aucun fichier de configuration trouvé");
|
||||
}
|
||||
else {
|
||||
self::$parameters = parse_ini_file($pathFile);
|
||||
}
|
||||
}
|
||||
return self::$parameters;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Framework/Request.php';
|
||||
require_once $GLOBALS['app_path'].'Framework/View.php';
|
||||
|
||||
abstract class Controller {
|
||||
|
||||
private $action;
|
||||
|
||||
protected $request;
|
||||
|
||||
public function setRequest(Request $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function executeAction($action) {
|
||||
if (method_exists($this, $action)) {
|
||||
$this->action = $action;
|
||||
$this->{$this->action}();
|
||||
}
|
||||
else {
|
||||
$classController = get_class($this);
|
||||
throw new Exception("Action '$action' non définie dans la classe $classController");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract function index();
|
||||
|
||||
protected function generateView($dataView = array(), $action = null) {
|
||||
|
||||
$actionView = $this->action;
|
||||
if ($action != null)
|
||||
$actionView = $action;
|
||||
|
||||
$classController = get_class($this);
|
||||
$controller = str_replace("Controller", "", $classController);
|
||||
$vue = new View($actionView, $controller);
|
||||
$vue->generate($dataView);
|
||||
}
|
||||
|
||||
protected function redirect($controller, $action = null)
|
||||
{
|
||||
$root = Configuration::get("root", "/");
|
||||
header("Location:" . $root . $controller . "/" . $action);
|
||||
}
|
||||
}
|
||||
32
server/webplatform/apps/CameraMonitor/Framework/Model.php
Normal file
32
server/webplatform/apps/CameraMonitor/Framework/Model.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
require_once $GLOBALS['app_path'].'Framework/Configuration.php';
|
||||
|
||||
abstract class Model
|
||||
{
|
||||
|
||||
private static $bdd;
|
||||
|
||||
protected function executeRequest($sql, $params = null)
|
||||
{
|
||||
if ($params == null) {
|
||||
$result = self::getBdd()->query($sql);
|
||||
}
|
||||
else {
|
||||
$result = self::getBdd()->prepare($sql);
|
||||
$result->execute($params);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function getBdd()
|
||||
{
|
||||
if (self::$bdd === null) {
|
||||
$dsn = Configuration::get("dsn");
|
||||
$login = Configuration::get("login");
|
||||
$mdp = Configuration::get("mdp");
|
||||
self::$bdd = new PDO($dsn, $login, $mdp,
|
||||
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
|
||||
}
|
||||
return self::$bdd;
|
||||
}
|
||||
}
|
||||
31
server/webplatform/apps/CameraMonitor/Framework/Request.php
Normal file
31
server/webplatform/apps/CameraMonitor/Framework/Request.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Framework/Session.php';
|
||||
|
||||
class Request {
|
||||
|
||||
private $parameters;
|
||||
private $session;
|
||||
|
||||
|
||||
public function __construct($parameters) {
|
||||
$this->parameters = $parameters;
|
||||
$this->session = new Session();
|
||||
}
|
||||
|
||||
public function existParameter($nom) {
|
||||
return (isset($this->parameters[$nom]) && $this->parameters[$nom] != "");
|
||||
}
|
||||
|
||||
public function getParameter($nom) {
|
||||
if ($this->existParameter($nom)) {
|
||||
return $this->parameters[$nom];
|
||||
}
|
||||
else
|
||||
throw new Exception("Paramètre '$nom' absent de la requête");
|
||||
}
|
||||
|
||||
public function getSession(){
|
||||
return $this->session;
|
||||
}
|
||||
}
|
||||
58
server/webplatform/apps/CameraMonitor/Framework/Router.php
Normal file
58
server/webplatform/apps/CameraMonitor/Framework/Router.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Framework/Request.php';
|
||||
require_once $GLOBALS['app_path'].'Framework/View.php';
|
||||
|
||||
class Router {
|
||||
|
||||
public function routingRequest() {
|
||||
try {
|
||||
$request = new Request(array_merge($_GET, $_POST));
|
||||
|
||||
$controller = $this->createController($request);
|
||||
$action = $this->createAction($request);
|
||||
|
||||
$controller->executeAction($action);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->error($e);
|
||||
}
|
||||
}
|
||||
|
||||
private function createController($request) {
|
||||
$controller = "Default";
|
||||
if ($request->existParameter('controller')) {
|
||||
$controller = $request->getParameter('controller');
|
||||
$controller = ucfirst(strtolower($controller));
|
||||
}
|
||||
|
||||
$classController = "Controller" . $controller;
|
||||
$fileController = $GLOBALS['app_path']."Controller/" . $classController . ".php";
|
||||
if (file_exists($fileController)) {
|
||||
|
||||
require($fileController);
|
||||
$controller = new $classController();
|
||||
$controller->setRequest($request);
|
||||
return $controller;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Fichier '$fileController' introuvable");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function createAction(Request $request) {
|
||||
$action = "index";
|
||||
if ($request->existParameter('action')) {
|
||||
$action = $request->getParameter('action');
|
||||
}
|
||||
return $action;
|
||||
}
|
||||
|
||||
private function error($exception) {
|
||||
$view = new View('error');
|
||||
$view->generate(array('msgError' => $exception->getMessage()));
|
||||
}
|
||||
|
||||
}
|
||||
35
server/webplatform/apps/CameraMonitor/Framework/Session.php
Normal file
35
server/webplatform/apps/CameraMonitor/Framework/Session.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
class Session
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
session_start();
|
||||
}
|
||||
|
||||
public function destruct()
|
||||
{
|
||||
session_destroy();
|
||||
}
|
||||
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
$_SESSION[$name] = $value;
|
||||
}
|
||||
|
||||
public function existAttribute($name)
|
||||
{
|
||||
return (isset($_SESSION[$name]) && $_SESSION[$name] != "");
|
||||
}
|
||||
|
||||
public function getAttribute($name)
|
||||
{
|
||||
if ($this->existAttribute($name)) {
|
||||
return $_SESSION[$name];
|
||||
}
|
||||
else {
|
||||
throw new Exception("Attribut '$name' absent de la session");
|
||||
}
|
||||
}
|
||||
}
|
||||
49
server/webplatform/apps/CameraMonitor/Framework/View.php
Normal file
49
server/webplatform/apps/CameraMonitor/Framework/View.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
require_once $GLOBALS['app_path'].'Framework/Configuration.php';
|
||||
|
||||
class View {
|
||||
|
||||
private $file;
|
||||
|
||||
public function __construct($action, $controller = "") {
|
||||
$file = $GLOBALS['app_path']."View/";
|
||||
if ($controller != "") {
|
||||
$file = $file . $controller . "/";
|
||||
}
|
||||
$this->file = $file . $action . ".php";
|
||||
}
|
||||
|
||||
public function generate($data) {
|
||||
$content = $this->generateFile($this->file, $data);
|
||||
|
||||
$title = "";
|
||||
$headScript = "";
|
||||
if(isset($data['title']))
|
||||
$title = $data['title'];
|
||||
if(isset($data['headScript']))
|
||||
$headScript = $data['headScript'];
|
||||
|
||||
$root = Configuration::get("root", "/");
|
||||
$vue = $this->generateFile($GLOBALS['app_path'].'View/template.php',
|
||||
array('headScript'=> $headScript, 'title' => $title, 'content' => $content,
|
||||
'root' => $root));
|
||||
echo $vue;
|
||||
}
|
||||
|
||||
private function generateFile($file, $data) {
|
||||
if (file_exists($file)) {
|
||||
extract($data);
|
||||
ob_start();
|
||||
require $file;
|
||||
return ob_get_clean();
|
||||
}
|
||||
else {
|
||||
throw new Exception("Fichier '$file' introuvable");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function clean($value) {
|
||||
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false);
|
||||
}
|
||||
}
|
||||
122
server/webplatform/apps/CameraMonitor/Model/Entity/Camera.php
Normal file
122
server/webplatform/apps/CameraMonitor/Model/Entity/Camera.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
class Camera
|
||||
{
|
||||
|
||||
private $id;
|
||||
private $name;
|
||||
private $product_key;
|
||||
private $available;
|
||||
private $enabled;
|
||||
private $rtmp_handle;
|
||||
|
||||
function __construct($id, $name, $product_key, $available, $enabled, $rtmp_handle)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->available = $available;
|
||||
$this->enabled = $enabled;
|
||||
$this->id = $id;
|
||||
$this->product_key = $product_key;
|
||||
$this->rtmp_handle = $rtmp_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRtmpHandle()
|
||||
{
|
||||
return $this->rtmp_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $rtmp_handle
|
||||
*/
|
||||
public function setRtmpHandle($rtmp_handle)
|
||||
{
|
||||
$this->rtmp_handle = $rtmp_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProductKey()
|
||||
{
|
||||
return $this->product_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $product_key
|
||||
*/
|
||||
public function setProductKey($product_key)
|
||||
{
|
||||
$this->product_key = $product_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAvailable()
|
||||
{
|
||||
return $this->available;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $available
|
||||
*/
|
||||
public function setAvailable($available)
|
||||
{
|
||||
$this->available = $available;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEnabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $enabled
|
||||
*/
|
||||
public function setEnabled($enabled)
|
||||
{
|
||||
$this->enabled = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
64
server/webplatform/apps/CameraMonitor/Model/Entity/User.php
Normal file
64
server/webplatform/apps/CameraMonitor/Model/Entity/User.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
class User {
|
||||
|
||||
private $id;
|
||||
private $login;
|
||||
private $password;
|
||||
|
||||
public function __construct($id, $login, $password) {
|
||||
$this->id = $id;
|
||||
$this->login = $login;
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLogin()
|
||||
{
|
||||
return $this->login;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $login
|
||||
*/
|
||||
public function setLogin($login)
|
||||
{
|
||||
$this->login = $login;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $password
|
||||
*/
|
||||
public function setPassword($password)
|
||||
{
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $id
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
85
server/webplatform/apps/CameraMonitor/Model/ModelCamera.php
Normal file
85
server/webplatform/apps/CameraMonitor/Model/ModelCamera.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Framework/Model.php';
|
||||
require_once $GLOBALS['app_path'].'Model/Entity/Camera.php';
|
||||
|
||||
class ModelCamera extends Model{
|
||||
|
||||
public function getCamera($camera_id, $user_id)
|
||||
{
|
||||
$sql = "select * from camera where id=?";
|
||||
$result = $this->executeRequest($sql, array($camera_id));
|
||||
if ( $result->rowCount() == 1)
|
||||
{
|
||||
$result = $result->fetch();
|
||||
$name = $this->getNameCameraByUser($user_id, $camera_id);
|
||||
return new Camera($result['id'], $name, $result['product_key'],$result['available'],$result['enabled'],$result['rtmp_handle']);
|
||||
}
|
||||
else
|
||||
throw new Exception("Aucune caméra ne correspond à cet identifiant");
|
||||
}
|
||||
|
||||
public function getNameCameraByUser($user_id, $camera_id)
|
||||
{
|
||||
$sql = "select name from user_camera where user_id=? and camera_id=?";
|
||||
$result = $this->executeRequest($sql, array($user_id, $camera_id));
|
||||
if($result->rowCount() == 1)
|
||||
return $result->fetch()['name'];
|
||||
else
|
||||
throw new Exception("Cet utilisateur n'as pas accès à cet caméra");
|
||||
}
|
||||
|
||||
public function addCamera($id, $product_key, $available, $enabled, $rtmp_handle)
|
||||
{
|
||||
$sql = "insert into camera values(?,?,?,?,?)";
|
||||
$this->executeRequest($sql, array($id, $product_key, $available, $enabled, $rtmp_handle));
|
||||
}
|
||||
|
||||
public function getAllCameraByUser($user_id)
|
||||
{
|
||||
$sql = "select * from user_camera where user_id=?";
|
||||
$result = $this->executeRequest($sql, array($user_id));
|
||||
$result = $result->fetchAll();
|
||||
$cameras = null;
|
||||
foreach($result as $cam)
|
||||
{
|
||||
$cameras[] = $this->getCamera($cam['camera_id'], $user_id);
|
||||
}
|
||||
|
||||
return $cameras;
|
||||
}
|
||||
|
||||
public function userCanAccessCam($user_id, $camera_id)
|
||||
{
|
||||
$sql = "select name from user_camera where user_id=? and camera_id=?";
|
||||
$result = $this->executeRequest($sql, array($user_id, $camera_id));
|
||||
return $result->rowCount() == 1;
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$sql = "delete from camera where id=?";
|
||||
$this->executeRequest($sql,array($id));
|
||||
}
|
||||
|
||||
public function exist($camera_id)
|
||||
{
|
||||
$sql = "select * from camera where id=? ";
|
||||
$result = $this->executeRequest($sql, array($camera_id));
|
||||
return ($result->rowCount() == 1);
|
||||
}
|
||||
|
||||
public function getCameraOnly($camera_id)
|
||||
{
|
||||
$sql = "select * from camera where id=?";
|
||||
$result = $this->executeRequest($sql, array($camera_id));
|
||||
if ( $result->rowCount() == 1)
|
||||
{
|
||||
$result = $result->fetch();
|
||||
return new Camera($result['id'], "", $result['product_key'],$result['available'],$result['enabled'],$result['rtmp_handle']);
|
||||
}
|
||||
else
|
||||
throw new Exception("Aucune caméra ne correspond à cet identifiant");
|
||||
}
|
||||
|
||||
}
|
||||
75
server/webplatform/apps/CameraMonitor/Model/ModelUser.php
Normal file
75
server/webplatform/apps/CameraMonitor/Model/ModelUser.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
require_once $GLOBALS['app_path'].'Framework/Model.php';
|
||||
require_once $GLOBALS['app_path'].'Model/Entity/User.php';
|
||||
|
||||
class ModelUser extends Model{
|
||||
|
||||
public function exist($login, $password)
|
||||
{
|
||||
$sql = "select id from user where login=? and password=?";
|
||||
$user = $this->executeRequest($sql, array($login, $password));
|
||||
return ($user->rowCount() == 1);
|
||||
}
|
||||
|
||||
public function getUser($login, $password)
|
||||
{
|
||||
$sql = "select * from user where login=? and password=?";
|
||||
$result = $this->executeRequest($sql, array($login, $password));
|
||||
if ( $result->rowCount() == 1)
|
||||
{
|
||||
$result = $result->fetch();
|
||||
return new User($result['id'],$result['login'],$result['password']);
|
||||
}
|
||||
else
|
||||
throw new Exception("Aucun utilisateur ne correspond aux identifiants fournis");
|
||||
}
|
||||
|
||||
public function addUser($login, $password)
|
||||
{
|
||||
$sql = "insert into user values('',?,?)";
|
||||
$this->executeRequest($sql, array($login, $password));
|
||||
}
|
||||
|
||||
public function getUserById($id)
|
||||
{
|
||||
$sql = "select * from user where id=?";
|
||||
$result = $this->executeRequest($sql, array($id));
|
||||
if ( $result->rowCount() == 1)
|
||||
{
|
||||
$result = $result->fetch();
|
||||
return new User($result['id'],$result['login'],$result['password']);
|
||||
}
|
||||
else
|
||||
throw new Exception("Aucun utilisateur ne correspond à l'id fournis");
|
||||
}
|
||||
|
||||
public function update($id,$login,$password)
|
||||
{
|
||||
$sql = "update user Set login=?, password=? where id=?";
|
||||
$this->executeRequest($sql, array($login,$password,$id));
|
||||
}
|
||||
|
||||
public function deleteCam($user_id, $camera_id)
|
||||
{
|
||||
$sql = "delete from user_camera where user_id=? and camera_id=?";
|
||||
$this->executeRequest($sql,array($user_id,$camera_id));
|
||||
}
|
||||
|
||||
public function addCam($user_id, $camera_id, $name)
|
||||
{
|
||||
$sql = "insert into user_camera values(?,?,?)";
|
||||
$this->executeRequest($sql, array($user_id, $camera_id, $name));
|
||||
}
|
||||
|
||||
public function haveCam($user_id, $camera_id)
|
||||
{
|
||||
$sql = "select * from user_camera where user_id=? and camera_id=?";
|
||||
$result = $this->executeRequest($sql,array($user_id, $camera_id));
|
||||
|
||||
if($result->rowCount() == 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<form method="get" action="default">
|
||||
<button type="submit">Retour</button>
|
||||
</form>
|
||||
|
||||
<form method="get" action="connexion/disconnect">
|
||||
<button type="submit">Deconnexion</button>
|
||||
</form>
|
||||
|
||||
<?php foreach($videos as $i => $video): ?>
|
||||
<h5>Du <?=$video["begin"]?> au <?=$video["end"]?></h5>
|
||||
<div id="rtmp-player-container-<?=$i?>"></div>
|
||||
<script>
|
||||
jwplayer("rtmp-player-container-<?=$i?>").setup({
|
||||
file: "<?=$video['path']?>",
|
||||
preload: false
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
|
||||
|
||||
37
server/webplatform/apps/CameraMonitor/View/Camera/index.php
Normal file
37
server/webplatform/apps/CameraMonitor/View/Camera/index.php
Normal file
@ -0,0 +1,37 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<form method="get" action="default">
|
||||
<button type="submit">Retour</button>
|
||||
</form>
|
||||
|
||||
<form method="get" action="connexion/disconnect">
|
||||
<button type="submit">Deconnexion</button>
|
||||
</form>
|
||||
|
||||
<form method="post" action="camera/swapState/<?=$this->clean($camera->getId())?>">
|
||||
<h2>Caméra : <?= $this->clean($camera->getName())?></h2>
|
||||
|
||||
<?php if($this->clean($camera->getAvailable()) == true):?> Joignable -
|
||||
<?php else: ?> Non joignable -
|
||||
<?php endif ?>
|
||||
|
||||
<?php if($this->clean($camera->getEnabled()) == true):?> Activée <button type="submit">Désactiver</button>
|
||||
<?php $swap = "disable";?>
|
||||
<?php else: ?> Désactivée <button type="submit">Activer</button>
|
||||
<?php $swap = "enable";?>
|
||||
<?php endif ?>
|
||||
<a href="camera/delayed/<?=$this->clean($camera->getId())?>"><button type="button">Regarder le différé</button></a>
|
||||
<input type="hidden" name="whereController" value="camera">
|
||||
<input type="hidden" name="whereAction" value="index/<?=$this->clean($camera->getId())?>">
|
||||
<input type="hidden" name="swap" value="<?=$swap?>">
|
||||
</form>
|
||||
<br>
|
||||
<div id="rtmp-player-container"></div>
|
||||
<script>
|
||||
jwplayer("rtmp-player-container").setup({
|
||||
file: "rtmp://<?=Configuration::get('host')?>:1935/livecam/<?=$this->clean($camera->getId())?>?login=<?=$this->clean($user->getLogin())?>&password=<?=$this->clean($user->getPassword())?>",
|
||||
controls: false,
|
||||
autostart: true,
|
||||
preload: "none"
|
||||
});
|
||||
</script>
|
||||
@ -0,0 +1,17 @@
|
||||
<?php $this->title = " Connexion" ?>
|
||||
|
||||
<p>Vous devez être connecté pour accéder au site.</p>
|
||||
|
||||
<form action="connexion/logOn" method="post">
|
||||
<input name="login" type="text" placeholder="Entrez votre login" required autofocus>
|
||||
<input name="password" type="password" placeholder="Entrez votre mot de passe" required>
|
||||
<button type="submit">Connexion</button>
|
||||
</form>
|
||||
|
||||
<form method="get" action="connexion/registration">
|
||||
<button type="submit">Inscription</button>
|
||||
</form>
|
||||
|
||||
<?php if (isset($msgError)): ?>
|
||||
<p><?= $msgError ?></p>
|
||||
<?php endif; ?>
|
||||
@ -0,0 +1,23 @@
|
||||
<?php $this->title = "Inscription" ?>
|
||||
|
||||
<p>Enregistrez vous pour avoir accès au site</p>
|
||||
|
||||
<form action="connexion/register" method="post" >
|
||||
<label>Login</label>
|
||||
<input type="text" name="login" size="30" placeholder="Entrez votre login" required autofocus/> <br/>
|
||||
|
||||
<label>Mot de passe</label>
|
||||
<input type="password" name="password" size="30" placeholder="Entrez votre Mot de passe" required /> <br/>
|
||||
|
||||
<label>Retapez votre mot de passe</label>
|
||||
<input type="password" name="passwordBis" size="30" placeholder="Entrez votre Mot de passe" required /> <br/>
|
||||
<button type="submit">Valider l'inscription</button>
|
||||
</form>
|
||||
|
||||
<form method="get" action="connexion">
|
||||
<button type="submit">Annuler l'inscription</button>
|
||||
</form>
|
||||
|
||||
<?php if (isset($msgError)): ?>
|
||||
<p><?= $msgError ?></p>
|
||||
<?php endif; ?>
|
||||
10
server/webplatform/apps/CameraMonitor/View/Default/admin.php
Normal file
10
server/webplatform/apps/CameraMonitor/View/Default/admin.php
Normal file
@ -0,0 +1,10 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<a href="connexion/disconnect"><button type="submit">Deconnexion</button></a>
|
||||
|
||||
<a href="default/addCamAdmin"><button type="submit">Ajouter une caméra</button></a>
|
||||
|
||||
<?php if(isset($id) && isset($product_key)):?>
|
||||
<p>Numéro de série de la caméra : <?= $this->clean($id) ?></p>
|
||||
<p>Clé produit de la caméra : <?= $this->clean($product_key) ?></p>
|
||||
<?php endif?>
|
||||
34
server/webplatform/apps/CameraMonitor/View/Default/index.php
Normal file
34
server/webplatform/apps/CameraMonitor/View/Default/index.php
Normal file
@ -0,0 +1,34 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<a href="connexion/disconnect"><button type="submit">Deconnexion</button></a>
|
||||
<a href="default/settings"><button type="submit">Paramètre</button></a>
|
||||
|
||||
<h2>Mes caméras</h2>
|
||||
|
||||
<?php if($cameras != null): ?>
|
||||
<ul>
|
||||
<?php foreach($cameras as $camera): ?>
|
||||
<li>
|
||||
<form method="post" action="camera/swapState/<?=$camera->getId()?>">
|
||||
<a href="<?= "camera/" . $this->clean($camera->getId()) ?>">
|
||||
<?= $camera->getName() ?>
|
||||
</a>
|
||||
|
||||
<?php if($camera->getAvailable() == true):?> Joignable -
|
||||
<?php else: ?> Non joignable -
|
||||
<?php endif ?>
|
||||
|
||||
<?php if($camera->getEnabled() == true):?> Activée <button type="submit">Désactiver</button>
|
||||
<?php $swap = "disable";?>
|
||||
<?php else: ?> Désactivée <button type="submit">Activer</button>
|
||||
<?php $swap = "enable";?>
|
||||
<?php endif ?>
|
||||
<a href="camera/delayed/<?=$camera->getId()?>"><button type="button">Regarder le différé</button></a>
|
||||
<input type="hidden" name="swap" value="<?=$swap?>">
|
||||
</form>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php else: ?>
|
||||
<p>Vous n'avez accès à aucune caméra</p>
|
||||
<?php endif ?>
|
||||
18
server/webplatform/apps/CameraMonitor/View/Default/live.php
Normal file
18
server/webplatform/apps/CameraMonitor/View/Default/live.php
Normal file
@ -0,0 +1,18 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<form method="get" action="default">
|
||||
<button type="submit">Retour</button>
|
||||
</form>
|
||||
|
||||
<form method="get" action="connexion/disconnect">
|
||||
<button type="submit">Deconnexion</button>
|
||||
</form>
|
||||
|
||||
<h2>Caméra : <?= $this->clean($camera->getName())?></h2>
|
||||
|
||||
<div id="rtmp-player-container"></div>
|
||||
<script>
|
||||
jwplayer("rtmp-player-container").setup({
|
||||
file: "rtmp://cam.wildsparksoftware.com:1935/livecam/<?=$this->clean($camera->getId())?>"
|
||||
});
|
||||
</script>
|
||||
@ -0,0 +1,61 @@
|
||||
<h1>Site web Projet L3</h1>
|
||||
|
||||
<a href="connexion/disconnect"><button type="submit">Deconnexion</button></a>
|
||||
<a href="default"><button type="submit">Retour</button></a>
|
||||
|
||||
<h3>Mes informations</h3>
|
||||
|
||||
<?php if(isset($messageInfo)): ?>
|
||||
<p><?= $messageInfo ?></p>
|
||||
<?php endif ?>
|
||||
<h4>Mes identifiants :</h4>
|
||||
<form method="post" action="default/updateLogin">
|
||||
<label>Login :</label>
|
||||
<input type="text" name="login" placeholder="Login" required>
|
||||
<button type="submit">Modifier</button>
|
||||
</form>
|
||||
|
||||
<form method="post" action="default/updatePassword">
|
||||
<label>Mot de passe :</label>
|
||||
<input type="password" name="password" placeholder="Mot de passe" required>
|
||||
<label>Vérification :</label>
|
||||
<input type="password" name="passwordBis" placeholder="Mot de passe" required>
|
||||
<button type="submit">Modifier</button>
|
||||
</form>
|
||||
|
||||
<h4>Mes caméras :</h4>
|
||||
<?php if($cameras != null): ?>
|
||||
<ul>
|
||||
<?php foreach($cameras as $camera): ?>
|
||||
<li>
|
||||
<form method="post" action="camera/swapState/<?=$camera->getId()?>">
|
||||
<a href="<?= "camera/" . $this->clean($camera->getId()) ?>">
|
||||
<?= $camera->getName() ?>
|
||||
</a>
|
||||
|
||||
<?php if($camera->getAvailable() == true):?> Joignable -
|
||||
<?php else: ?> Non joignable -
|
||||
<?php endif ?>
|
||||
|
||||
<?php if($camera->getEnabled() == true):?> Activée <button type="submit">Désactiver</button>
|
||||
<?php $swap = "disable";?>
|
||||
<?php else: ?> Désactivée <button type="submit">Activer</button>
|
||||
<?php $swap = "enable";?>
|
||||
<?php endif ?>
|
||||
<input type="hidden" name="swap" value="<?=$swap?>">
|
||||
<input type="hidden" name="whereAction" value="settings">
|
||||
<a href="camera/delete/<?=$camera->getId()?>"><button type="button">Supprimer</button></a>
|
||||
</form>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php else: ?>
|
||||
<p>Vous n'avez accès à aucune caméra</p>
|
||||
<?php endif ?>
|
||||
<form method="post" action="default/addCam">
|
||||
<label>Nom :</label>
|
||||
<input type="text" name="name" placeholder="Entrez un nom" required>
|
||||
<label>Numéro de série :</label>
|
||||
<input type="text" name="camera_id" placeholder="Entrez le numéro de série" required>
|
||||
<button type="submit">Ajouter Caméra</button>
|
||||
</form>
|
||||
18
server/webplatform/apps/CameraMonitor/View/error.php
Normal file
18
server/webplatform/apps/CameraMonitor/View/error.php
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Erreur</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>ERREUR !!!!!</h1>
|
||||
<?php
|
||||
if (isset($msgError))
|
||||
echo $msgError;
|
||||
?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
15
server/webplatform/apps/CameraMonitor/View/template.php
Normal file
15
server/webplatform/apps/CameraMonitor/View/template.php
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<base href="<?= $root ?>" >
|
||||
<link rel="stylesheet" href="Content/myStyle.css" />
|
||||
<title><?= $title ?></title>
|
||||
<?= $headScript ?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<?= $content ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
2
server/webplatform/www/.htaccess
Normal file
2
server/webplatform/www/.htaccess
Normal file
@ -0,0 +1,2 @@
|
||||
RewriteEngine on
|
||||
RewriteRule ^([a-zA-Z]*)/?([a-zA-Z]*)?/?([a-zA-Z0-9]*)?/?$ index.php?controller=$1&action=$2&id=$3 [NC,L]
|
||||
1
server/webplatform/www/Content/myStyle.css
Normal file
1
server/webplatform/www/Content/myStyle.css
Normal file
@ -0,0 +1 @@
|
||||
|
||||
25
server/webplatform/www/camera-auth/index.php
Normal file
25
server/webplatform/www/camera-auth/index.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
$GLOBALS['app_path'] = '../../apps/CameraMonitor/';
|
||||
|
||||
require $GLOBALS['app_path'].'Model/ModelCamera.php';
|
||||
|
||||
if(isset($_POST['name']) && isset($_POST['rtmp_handle']))
|
||||
{
|
||||
$idCam = $_POST['name'];
|
||||
$rtmp_handle = $_POST['rtmp_handle'];
|
||||
$modelCamera = new ModelCamera();
|
||||
if($modelCamera->exist($idCam) && $rtmp_handle != "")
|
||||
{
|
||||
$camera = $modelCamera->getCameraOnly($idCam);
|
||||
if($camera->getRtmpHandle() == $rtmp_handle)
|
||||
http_response_code(200);
|
||||
else
|
||||
http_response_code(403);
|
||||
}
|
||||
else
|
||||
http_response_code(403);
|
||||
}
|
||||
else
|
||||
http_response_code(403);
|
||||
?>
|
||||
25
server/webplatform/www/client-auth/index.php
Normal file
25
server/webplatform/www/client-auth/index.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
$GLOBALS['app_path'] = '../../apps/CameraMonitor/';
|
||||
|
||||
require $GLOBALS['app_path'].'Model/ModelUser.php';
|
||||
|
||||
if(isset($_POST['name']) && isset($_POST['login']) && isset($_POST['password']) )
|
||||
{
|
||||
$idCam = $_POST['name'];
|
||||
$login = $_POST['login'];
|
||||
$password = $_POST['password'];
|
||||
$modelUser = new ModelUser();
|
||||
if($modelUser->exist($login, $password))
|
||||
{
|
||||
if($modelUser->haveCam($modelUser->getUser($login,$password)->getId(),$idCam) || $login == "root")
|
||||
http_response_code(200);
|
||||
else
|
||||
http_response_code(403);
|
||||
}
|
||||
else
|
||||
http_response_code(403);
|
||||
}
|
||||
else
|
||||
http_response_code(403);
|
||||
?>
|
||||
10
server/webplatform/www/index.php
Normal file
10
server/webplatform/www/index.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
$GLOBALS['app_path'] = '../apps/CameraMonitor/';
|
||||
|
||||
require $GLOBALS['app_path'].'Framework/Router.php';
|
||||
|
||||
$controller = new Router();
|
||||
$controller->routingRequest()
|
||||
|
||||
?>
|
||||
BIN
server/webplatform/www/jwplayer/jwplayer.flash.swf
Normal file
BIN
server/webplatform/www/jwplayer/jwplayer.flash.swf
Normal file
Binary file not shown.
7
server/webplatform/www/jwplayer/jwplayer.js
Normal file
7
server/webplatform/www/jwplayer/jwplayer.js
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/polyfills.base64.js
Normal file
1
server/webplatform/www/jwplayer/polyfills.base64.js
Normal file
@ -0,0 +1 @@
|
||||
webpackJsonpjwplayer([2],{105:function(a,b,c){var d,e;d=[],e=function(){function a(a){this.message=a}var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";a.prototype=new Error,a.prototype.name="InvalidCharacterError",window.btoa||(window.btoa=function(c){for(var d,e,f=String(c),g=0,h=b,i="";f.charAt(0|g)||(h="=",g%1);i+=h.charAt(63&d>>8-g%1*8)){if(e=f.charCodeAt(g+=.75),e>255)throw new a("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");d=d<<8|e}return i}),window.atob||(window.atob=function(c){var d=String(c).replace(/=+$/,"");if(d.length%4==1)throw new a("'atob' failed: The string to be decoded is not correctly encoded.");for(var e,f,g=0,h=0,i="";f=d.charAt(h++);~f&&(e=g%4?64*e+f:f,g++%4)?i+=String.fromCharCode(255&e>>(-2*g&6)):0)f=b.indexOf(f);return i})}.apply(b,d),!(void 0!==e&&(a.exports=e))}});
|
||||
1
server/webplatform/www/jwplayer/polyfills.promise.js
Normal file
1
server/webplatform/www/jwplayer/polyfills.promise.js
Normal file
@ -0,0 +1 @@
|
||||
webpackJsonpjwplayer([1],{104:function(a,b,c){var d,e;d=[c(45)],e=function(a){function b(a,b){return function(){a.apply(b,arguments)}}function c(a){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof a)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],i(a,b(e,this),b(f,this))}function d(a){var b=this;return null===this._state?void this._deferreds.push(a):void j(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(e){return void a.reject(e)}a.resolve(d)})}function e(a){try{if(a===this)throw new TypeError("A promise cannot be resolved with itself.");if(a&&("object"==typeof a||"function"==typeof a)){var c=a.then;if("function"==typeof c)return void i(b(c,a),b(e,this),b(f,this))}this._state=!0,this._value=a,g.call(this)}catch(d){f.call(this,d)}}function f(a){this._state=!1,this._value=a,g.call(this)}function g(){for(var a=0,b=this._deferreds.length;b>a;a++)d.call(this,this._deferreds[a]);this._deferreds=null}function h(a,b,c,d){this.onFulfilled="function"==typeof a?a:null,this.onRejected="function"==typeof b?b:null,this.resolve=c,this.reject=d}function i(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(e){if(d)return;d=!0,c(e)}}var j=a.defer,k=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};c.prototype["catch"]=function(a){return this.then(null,a)},c.prototype.then=function(a,b){var e=this;return new c(function(c,f){d.call(e,new h(a,b,c,f))})},c.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&k(arguments[0])?arguments[0]:arguments);return new c(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(i){c(i)}}if(0===a.length)return b([]);for(var e=a.length,f=0;f<a.length;f++)d(f,a[f])})},c.resolve=function(a){return a&&"object"==typeof a&&a.constructor===c?a:new c(function(b){b(a)})},c.reject=function(a){return new c(function(b,c){c(a)})},c.race=function(a){return new c(function(b,c){for(var d=0,e=a.length;e>d;d++)a[d].then(b,c)})},c._setImmediateFn=function(a){j=a},window.Promise||(window.Promise=c)}.apply(b,d),!(void 0!==e&&(a.exports=e))}});
|
||||
1
server/webplatform/www/jwplayer/provider.cast.js
Normal file
1
server/webplatform/www/jwplayer/provider.cast.js
Normal file
File diff suppressed because one or more lines are too long
4
server/webplatform/www/jwplayer/provider.shaka.js
Normal file
4
server/webplatform/www/jwplayer/provider.shaka.js
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/provider.youtube.js
Normal file
1
server/webplatform/www/jwplayer/provider.youtube.js
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/skins/beelden.css
Normal file
1
server/webplatform/www/jwplayer/skins/beelden.css
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/skins/bekle.css
Normal file
1
server/webplatform/www/jwplayer/skins/bekle.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-bekle .jw-background-color{background:linear-gradient(to bottom,#323b4c,#2f3847 50%,#323b4c 100%)}.jw-skin-bekle .jw-controlbar{background:rgba(24,35,53,0.8)}.jw-skin-bekle .jw-text{color:#fff}.jw-skin-bekle .jw-tooltip-title{color:#fff}.jw-skin-bekle .jw-knob{color:#fff}.jw-skin-bekle .jw-button-color{color:#fff}.jw-skin-bekle .jw-button-color:hover{color:#139ed5}.jw-skin-bekle .jw-toggle{color:#139ed5}.jw-skin-bekle .jw-toggle.jw-off{color:#fff}.jw-skin-bekle .jw-option{color:#fff}.jw-skin-bekle .jw-option.jw-active-option{color:#139ed5}.jw-skin-bekle .jw-icon-display{color:#fff}.jw-skin-bekle .jw-display-icon-container{border-radius:.5em}.jw-skin-bekle .jw-display-icon-container:hover{background:#139ed5}.jw-skin-bekle .jw-display-icon-container:hover .jw-icon-display{color:#fff}.jw-skin-bekle .jw-rail{background:linear-gradient(to bottom,#323b4c,#2f3847 50%,#323b4c 100%)}.jw-skin-bekle .jw-buffer{background:linear-gradient(to bottom,#5e6575,#565e6b 50%,#5e6575 100%)}.jw-skin-bekle .jw-progress{background:linear-gradient(to bottom,#15b2f0,#149bd1 50%,#15b2f0 100%)}.jw-skin-bekle .jw-slider-horizontal{background:rgba(24,35,53,0.8)}.jw-skin-bekle .jw-slider-horizontal .jw-knob{margin-left:-0.325em}.jw-skin-bekle .jw-slider-vertical .jw-knob{margin-bottom:-0.325em}.jw-skin-bekle .jw-time-tip,.jw-skin-bekle .jw-volume-tip,.jw-skin-bekle .jw-menu{background:rgba(80,88,99,0.9);border:0;padding:.5em}.jw-skin-bekle .jw-skip{background:rgba(24,35,53,0.8);padding:.5em}.jw-skin-bekle .jw-skip .jw-skip-icon{color:#fff}.jw-skin-bekle .jw-skip.jw-skippable:hover .jw-skip-icon,.jw-skin-bekle .jw-skip.jw-skippable:hover .jw-text{color:#139ed5}.jw-skin-bekle .jw-time-tip .jw-text,.jw-skin-bekle .jw-dock-button .jw-text{color:#bbb}.jw-skin-bekle .jw-time-tip{bottom:1em}.jw-skin-bekle .jw-dock-button{background:linear-gradient(to bottom,#323b4c,#2f3847 50%,#323b4c 100%);border-radius:.5em}.jw-skin-bekle .jw-dock-button:hover{background:#139ed5}.jw-skin-bekle .jw-playlist-container{padding:0}.jw-skin-bekle .jw-icon-inline,.jw-skin-bekle .jw-icon-tooltip,.jw-skin-bekle .jw-text-elapsed,.jw-skin-bekle .jw-text-duration{padding:0 .25em}.jw-skin-bekle .jw-controlbar{display:inline-block;width:96%;max-width:50em;margin:0 auto;bottom:.7em;left:2%;right:2%}.jw-skin-bekle.jw-flag-audio-player .jw-controlbar{bottom:0}.jw-skin-bekle .jw-controlbar{border-radius:.3em}.jw-skin-bekle .jw-playlist-container{left:-42%;overflow:hidden;bottom:.2em}.jw-skin-bekle .jw-playlist-container .jw-option{border-bottom:1px solid rgba(24,35,53,0.8)}.jw-skin-bekle .jw-playlist-container .jw-option:hover,.jw-skin-bekle .jw-playlist-container .jw-option.jw-active-option{background-color:rgba(24,35,53,0.8);color:#139ed5}.jw-skin-bekle .jw-playlist-container ::-webkit-scrollbar-track{background-color:#222c37}.jw-skin-bekle .jw-playlist-container ::-webkit-scrollbar{width:2px;border:10px solid rgba(24,35,53,0.8);border-radius:.3em}.jw-skin-bekle .jw-playlist-container ::-webkit-scrollbar-thumb{background-color:#fff}.jw-skin-bekle .jw-tooltip-title{border-bottom:1px solid rgba(24,35,53,0.8);background-color:rgba(24,35,53,0.8)}.jw-skin-bekle .jw-slider-horizontal .jw-rail,.jw-skin-bekle .jw-slider-vertical .jw-rail,.jw-skin-bekle .jw-slider-horizontal .jw-progress,.jw-skin-bekle .jw-slider-vertical .jw-progress,.jw-skin-bekle .jw-slider-horizontal .jw-buffer,.jw-skin-bekle .jw-slider-vertical .jw-buffer{border-radius:.5em}.jw-skin-bekle .jw-slider-horizontal .jw-knob,.jw-skin-bekle .jw-slider-vertical .jw-knob{background-color:#fff;width:.7em;height:.7em;border-radius:50%}.jw-skin-bekle .jw-slider-horizontal{background:transparent}.jw-skin-bekle .jw-slider-horizontal .jw-rail,.jw-skin-bekle .jw-slider-horizontal .jw-progress,.jw-skin-bekle .jw-slider-horizontal .jw-buffer{height:.3em}.jw-skin-bekle .jw-slider-horizontal .jw-cue{top:.04999999999999999em;background-color:#fff;width:.2em;height:.2em;border-radius:1em}.jw-skin-bekle .jw-slider-horizontal .jw-knob{top:-0.19999999999999998em}.jw-skin-bekle .jw-slider-vertical .jw-rail,.jw-skin-bekle .jw-slider-vertical .jw-progress{width:.3em}.jw-skin-bekle .jw-slider-vertical .jw-rail{background:linear-gradient(to right,#323b4c,#2f3847 50%,#323b4c 100%)}.jw-skin-bekle .jw-slider-vertical .jw-progress{background:linear-gradient(to right,#15b2f0,#149bd1 50%,#15b2f0 100%)}.jw-skin-bekle .jw-time-tip,.jw-skin-bekle .jw-volume-tip,.jw-skin-bekle .jw-menu,.jw-skin-bekle .jw-skip{border-radius:.3em}.jw-skin-bekle .jw-volume-tip,.jw-skin-bekle .jw-menu{bottom:.2em}
|
||||
1
server/webplatform/www/jwplayer/skins/five.css
Normal file
1
server/webplatform/www/jwplayer/skins/five.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-five .jw-background-color{background:rgba(51,51,51,0.7)}.jw-skin-five .jw-controlbar{background:rgba(238,238,238,0.8)}.jw-skin-five .jw-text{color:#464646}.jw-skin-five .jw-tooltip-title{color:#464646}.jw-skin-five .jw-knob{color:#464646}.jw-skin-five .jw-button-color{color:#464646}.jw-skin-five .jw-button-color:hover{color:#000}.jw-skin-five .jw-toggle{color:#000}.jw-skin-five .jw-toggle.jw-off{color:#464646}.jw-skin-five .jw-option{color:#464646}.jw-skin-five .jw-option.jw-active-option{color:#000}.jw-skin-five .jw-icon-display{color:rgba(238,238,238,0.8)}.jw-skin-five .jw-display-icon-container{border-radius:.5em}.jw-skin-five .jw-display-icon-container:hover{background:#333}.jw-skin-five .jw-display-icon-container:hover .jw-icon-display{color:#fff}.jw-skin-five .jw-rail{background:#b8b6b7}.jw-skin-five .jw-buffer{background:#9c9a9d}.jw-skin-five .jw-progress{background:#000}.jw-skin-five .jw-slider-horizontal{background:rgba(238,238,238,0.8)}.jw-skin-five .jw-slider-horizontal .jw-knob{margin-left:-0.5em}.jw-skin-five .jw-slider-vertical .jw-knob{margin-bottom:-0.5em}.jw-skin-five .jw-time-tip,.jw-skin-five .jw-volume-tip,.jw-skin-five .jw-menu{background:#333;border:0;padding:.5em}.jw-skin-five .jw-skip{background:rgba(238,238,238,0.8);padding:.5em}.jw-skin-five .jw-skip .jw-skip-icon{color:#464646}.jw-skin-five .jw-skip.jw-skippable:hover .jw-skip-icon,.jw-skin-five .jw-skip.jw-skippable:hover .jw-text{color:#000}.jw-skin-five .jw-time-tip .jw-text,.jw-skin-five .jw-dock-button .jw-text{color:#bbb}.jw-skin-five .jw-time-tip{bottom:1em}.jw-skin-five .jw-dock-button{background:rgba(51,51,51,0.7);border-radius:.5em}.jw-skin-five .jw-dock-button:hover{background:#333}.jw-skin-five .jw-playlist-container{padding:0}.jw-skin-five .jw-icon-inline,.jw-skin-five .jw-icon-tooltip,.jw-skin-five .jw-text-elapsed,.jw-skin-five .jw-text-duration{padding:0 .25em}.jw-skin-five .jw-display-icon-container{border-radius:0}.jw-skin-five .jw-option{color:#bbb}.jw-skin-five .jw-option:hover,.jw-skin-five .jw-option.jw-active-option{color:#fff}.jw-skin-five .jw-playlist-container{left:-42%;background-color:#fff}.jw-skin-five .jw-playlist-container .jw-option{border-bottom:1px solid #ececec;background-color:#fff;margin-right:8px;color:#464646}.jw-skin-five .jw-playlist-container .jw-option:hover,.jw-skin-five .jw-playlist-container .jw-option.jw-active-option{background-color:#ececec;color:#000}.jw-skin-five .jw-playlist-container .jw-option:hover{color:#000}.jw-skin-five .jw-playlist-container .jw-label .jw-icon-play{color:#000}.jw-skin-five .jw-playlist-container ::-webkit-scrollbar-track{background-color:#ececec}.jw-skin-five .jw-playlist-container ::-webkit-scrollbar{width:2px;border:10px solid #fff}.jw-skin-five .jw-playlist-container ::-webkit-scrollbar-thumb{background-color:#000}.jw-skin-five .jw-tooltip-title{border-bottom:1px solid #000;background-color:#ececec}.jw-skin-five .jw-slider-horizontal{background:transparent}.jw-skin-five .jw-slider-horizontal .jw-slider-container{height:.9em}.jw-skin-five .jw-slider-horizontal .jw-rail,.jw-skin-five .jw-slider-horizontal .jw-buffer,.jw-skin-five .jw-slider-horizontal .jw-progress{height:.2em;border-radius:0}.jw-skin-five .jw-slider-horizontal .jw-rail{box-shadow:none}.jw-skin-five .jw-slider-horizontal .jw-knob{top:-0.4em;margin:0;background-color:#000;border-radius:0;width:1px;height:1em}.jw-skin-five .jw-slider-horizontal .jw-cue{top:-0.1em;width:.1em;height:.4em;background-color:#000;border-left:1px solid #fff;border-right:1px solid #fff}.jw-skin-five .jw-slider-vertical .jw-rail,.jw-skin-five .jw-slider-vertical .jw-progress{width:.2em}.jw-skin-five .jw-slider-vertical .jw-progress{background:#fff}.jw-skin-five .jw-slider-vertical .jw-rail{background:#737373}.jw-skin-five .jw-slider-vertical .jw-knob{margin-bottom:-1px;width:.6em;background:linear-gradient(to bottom,#fff 0,#fff 30%,#333 100%);border-radius:0;height:2px;width:100%}.jw-skin-five .jw-dock-button{border-radius:0}
|
||||
1
server/webplatform/www/jwplayer/skins/glow.css
Normal file
1
server/webplatform/www/jwplayer/skins/glow.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-glow .jw-background-color{background:rgba(51,51,51,0.8)}.jw-skin-glow .jw-background-color{background:#333}.jw-skin-glow .jw-controlbar{background:rgba(19,20,21,0.8)}.jw-skin-glow .jw-text{color:#fff}.jw-skin-glow .jw-tooltip-title{color:#fff}.jw-skin-glow .jw-knob{color:#fff}.jw-skin-glow .jw-button-color{color:#fff}.jw-skin-glow .jw-button-color:hover{color:#fff}.jw-skin-glow .jw-toggle{color:#fff}.jw-skin-glow .jw-toggle.jw-off{color:#fff}.jw-skin-glow .jw-option{color:#fff}.jw-skin-glow .jw-option.jw-active-option{color:#fff}.jw-skin-glow .jw-icon-display{color:#fff}.jw-skin-glow .jw-display-icon-container{border-radius:.5em}.jw-skin-glow .jw-display-icon-container:hover{background:#4d4d4d}.jw-skin-glow .jw-display-icon-container:hover .jw-icon-display{color:#fff}.jw-skin-glow .jw-rail{background:#2a2c2e}.jw-skin-glow .jw-buffer{background:#3b3d41}.jw-skin-glow .jw-progress{background:#fff}.jw-skin-glow .jw-slider-horizontal{background:rgba(19,20,21,0.8)}.jw-skin-glow .jw-slider-horizontal .jw-knob{margin-left:-0.325em}.jw-skin-glow .jw-slider-vertical .jw-knob{margin-bottom:-0.325em}.jw-skin-glow .jw-time-tip,.jw-skin-glow .jw-volume-tip,.jw-skin-glow .jw-menu{background:#333;border:0;padding:.5em}.jw-skin-glow .jw-skip{background:rgba(19,20,21,0.8);padding:.5em}.jw-skin-glow .jw-skip .jw-skip-icon{color:#fff}.jw-skin-glow .jw-skip.jw-skippable:hover .jw-skip-icon,.jw-skin-glow .jw-skip.jw-skippable:hover .jw-text{color:#fff}.jw-skin-glow .jw-time-tip .jw-text,.jw-skin-glow .jw-dock-button .jw-text{color:#bbb}.jw-skin-glow .jw-time-tip{bottom:1em}.jw-skin-glow .jw-dock-button{background:#333;border-radius:.5em}.jw-skin-glow .jw-dock-button:hover{background:#4d4d4d}.jw-skin-glow .jw-playlist-container{padding:0}.jw-skin-glow .jw-icon-inline,.jw-skin-glow .jw-icon-tooltip,.jw-skin-glow .jw-text-elapsed,.jw-skin-glow .jw-text-duration{padding:0 .25em}.jw-skin-glow .jw-time-tip,.jw-skin-glow .jw-volume-tip,.jw-skin-glow .jw-menu,.jw-skin-glow .jw-skip{border-radius:.25em}.jw-skin-glow .jw-volume-tip,.jw-skin-glow .jw-menu{bottom:.3em}.jw-skin-glow .jw-playlist-container{left:-42%;bottom:0;border-radius:0}.jw-skin-glow .jw-playlist-container .jw-option{border-bottom:1px solid #000;color:#fff}.jw-skin-glow .jw-playlist-container .jw-option:hover,.jw-skin-glow .jw-playlist-container .jw-option.jw-active-option{background-color:rgba(19,20,21,0.8);color:#fff}.jw-skin-glow .jw-playlist-container ::-webkit-scrollbar-track{background-color:#000}.jw-skin-glow .jw-playlist-container ::-webkit-scrollbar{border:10px solid #3b3d41}.jw-skin-glow .jw-playlist-container ::-webkit-scrollbar-thumb{background-color:#fff}.jw-skin-glow .jw-tooltip-title{border-bottom:1px solid #000;background-color:#3b3d41}.jw-skin-glow .jw-rail,.jw-skin-glow .jw-buffer,.jw-skin-glow .jw-progress{border-radius:.5em}.jw-skin-glow .jw-knob{display:none}.jw-skin-glow .jw-slider-horizontal{background:transparent}.jw-skin-glow .jw-slider-horizontal .jw-cue{top:.07500000000000001em;background-color:#000;width:.25em;height:.25em;border-radius:1em}.jw-skin-glow .jw-slider-vertical{bottom:5px}.jw-skin-glow .jw-slider-vertical .jw-rail{background-color:#141516}.jw-skin-glow .jw-slider-vertical .jw-rail,.jw-skin-glow .jw-slider-vertical .jw-progress{width:.4em}
|
||||
1
server/webplatform/www/jwplayer/skins/roundster.css
Normal file
1
server/webplatform/www/jwplayer/skins/roundster.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-roundster .jw-background-color{background:#8490a0}.jw-skin-roundster .jw-controlbar{background:#dfe2e9}.jw-skin-roundster .jw-text{color:#8490a0}.jw-skin-roundster .jw-tooltip-title{color:#8490a0}.jw-skin-roundster .jw-knob{color:#8490a0}.jw-skin-roundster .jw-button-color{color:#8490a0}.jw-skin-roundster .jw-button-color:hover{color:#f15173}.jw-skin-roundster .jw-toggle{color:#f15173}.jw-skin-roundster .jw-toggle.jw-off{color:#8490a0}.jw-skin-roundster .jw-option{color:#8490a0}.jw-skin-roundster .jw-option.jw-active-option{color:#f15173}.jw-skin-roundster .jw-icon-display{color:rgba(255,255,255,0.5)}.jw-skin-roundster .jw-display-icon-container{border-radius:.5em}.jw-skin-roundster .jw-display-icon-container:hover{background:#f15173}.jw-skin-roundster .jw-display-icon-container:hover .jw-icon-display{color:#fff}.jw-skin-roundster .jw-rail{background:#878fa2}.jw-skin-roundster .jw-buffer{background:#9c9a9d}.jw-skin-roundster .jw-progress{background:#f15173}.jw-skin-roundster .jw-slider-horizontal{background:#dfe2e9}.jw-skin-roundster .jw-slider-horizontal .jw-knob{margin-left:-0.45em}.jw-skin-roundster .jw-slider-vertical .jw-knob{margin-bottom:-0.45em}.jw-skin-roundster .jw-time-tip,.jw-skin-roundster .jw-volume-tip,.jw-skin-roundster .jw-menu{background:#5c6373;border:0;padding:.5em}.jw-skin-roundster .jw-skip{background:#dfe2e9;padding:.5em}.jw-skin-roundster .jw-skip .jw-skip-icon{color:#8490a0}.jw-skin-roundster .jw-skip.jw-skippable:hover .jw-skip-icon,.jw-skin-roundster .jw-skip.jw-skippable:hover .jw-text{color:#f15173}.jw-skin-roundster .jw-time-tip .jw-text,.jw-skin-roundster .jw-dock-button .jw-text{color:#bbb}.jw-skin-roundster .jw-time-tip{bottom:1em}.jw-skin-roundster .jw-dock-button{background:#8490a0;border-radius:.5em}.jw-skin-roundster .jw-dock-button:hover{background:#f15173}.jw-skin-roundster .jw-playlist-container{padding:0}.jw-skin-roundster .jw-icon-inline,.jw-skin-roundster .jw-icon-tooltip,.jw-skin-roundster .jw-text-elapsed,.jw-skin-roundster .jw-text-duration{padding:0 .25em}.jw-skin-roundster .jw-controlbar{display:inline-block;width:96%;max-width:50em;margin:0 auto;bottom:.7em;left:2%;right:2%}.jw-skin-roundster.jw-flag-audio-player .jw-controlbar{bottom:0}.jw-skin-roundster .jw-controlbar{border-radius:1em;padding:0 1em}.jw-skin-roundster .jw-playlist-container{left:-48%;background-color:#878fa2;border-radius:.3em;overflow:hidden}.jw-skin-roundster .jw-playlist-container .jw-option,.jw-skin-roundster .jw-playlist-container .jw-text,.jw-skin-roundster .jw-playlist-container .jw-icon{color:#cbd0da}.jw-skin-roundster .jw-playlist-container .jw-option{border-bottom:1px solid #747d92;background-color:#878fa2}.jw-skin-roundster .jw-playlist-container .jw-option:hover,.jw-skin-roundster .jw-playlist-container .jw-option.jw-active-option{background-color:#747d92;color:#fff}.jw-skin-roundster .jw-playlist-container .jw-label .jw-icon-play{color:#f15173}.jw-skin-roundster .jw-playlist-container ::-webkit-scrollbar-track{background-color:#747d92}.jw-skin-roundster .jw-playlist-container ::-webkit-scrollbar{border:10px solid #878fa2}.jw-skin-roundster .jw-playlist-container ::-webkit-scrollbar-thumb{background-color:white}.jw-skin-roundster .jw-tooltip-title{border-bottom:1px solid #747d92;background-color:#878fa2}.jw-skin-roundster .jw-rail,.jw-skin-roundster .jw-progress,.jw-skin-roundster .jw-buffer{border-radius:1em}.jw-skin-roundster .jw-knob{background-color:#fff;width:.9em;height:.9em;border-radius:50%;box-shadow:0 1px 5px 1px #868ea3}.jw-skin-roundster .jw-slider-horizontal .jw-cue{top:.07500000000000001em;width:.25em;height:.25em;border-radius:50%;background-color:#fff}.jw-skin-roundster .jw-slider-horizontal .jw-knob{top:-0.25em}.jw-skin-roundster .jw-slider-vertical .jw-rail{background-color:#434853}.jw-skin-roundster .jw-slider-vertical .jw-rail,.jw-skin-roundster .jw-slider-vertical .jw-progress{width:.4em}.jw-skin-roundster .jw-time-tip,.jw-skin-roundster .jw-volume-tip,.jw-skin-roundster .jw-menu{border-radius:.25em}.jw-skin-roundster .jw-volume-tip,.jw-skin-roundster .jw-menu{bottom:.3em}.jw-skin-roundster .jw-dock .jw-dock-button{border-radius:50%}.jw-skin-roundster .jw-dock .jw-overlay{border-radius:2.5em}.jw-skin-roundster .jw-skip{border-radius:1em;padding:.25em 1em}
|
||||
1
server/webplatform/www/jwplayer/skins/seven.css
Normal file
1
server/webplatform/www/jwplayer/skins/seven.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-seven .jw-background-color{background:#000}.jw-skin-seven .jw-controlbar{border-top:#333 1px solid;height:2.5em}.jw-skin-seven .jw-group{vertical-align:middle}.jw-skin-seven .jw-playlist{background-color:rgba(0,0,0,0.5)}.jw-skin-seven .jw-playlist-container{left:-43%;background-color:rgba(0,0,0,0.5)}.jw-skin-seven .jw-playlist-container .jw-option{border-bottom:1px solid #444}.jw-skin-seven .jw-playlist-container .jw-option:hover,.jw-skin-seven .jw-playlist-container .jw-option.jw-active-option{background-color:black}.jw-skin-seven .jw-playlist-container .jw-option:hover .jw-label{color:#ff0046}.jw-skin-seven .jw-playlist-container .jw-icon-playlist{margin-left:0}.jw-skin-seven .jw-playlist-container .jw-label .jw-icon-play{color:#ff0046}.jw-skin-seven .jw-playlist-container .jw-label .jw-icon-play:before{padding-left:0}.jw-skin-seven .jw-tooltip-title{background-color:#000;color:#fff}.jw-skin-seven .jw-text{color:#fff}.jw-skin-seven .jw-button-color{color:#fff}.jw-skin-seven .jw-button-color:hover{color:#ff0046}.jw-skin-seven .jw-toggle{color:#ff0046}.jw-skin-seven .jw-toggle.jw-off{color:#fff}.jw-skin-seven .jw-controlbar .jw-icon:before,.jw-skin-seven .jw-text-elapsed,.jw-skin-seven .jw-text-duration{padding:0 .7em}.jw-skin-seven .jw-controlbar .jw-icon-prev:before{padding-right:.25em}.jw-skin-seven .jw-controlbar .jw-icon-playlist:before{padding:0 .45em}.jw-skin-seven .jw-controlbar .jw-icon-next:before{padding-left:.25em}.jw-skin-seven .jw-icon-prev,.jw-skin-seven .jw-icon-next{font-size:.7em}.jw-skin-seven .jw-icon-prev:before{border-left:1px solid #666}.jw-skin-seven .jw-icon-next:before{border-right:1px solid #666}.jw-skin-seven .jw-icon-display{color:#fff}.jw-skin-seven .jw-icon-display:before{padding-left:0}.jw-skin-seven .jw-display-icon-container{border-radius:50%;border:1px solid #333}.jw-skin-seven .jw-rail{background-color:#384154;box-shadow:none}.jw-skin-seven .jw-buffer{background-color:#666f82}.jw-skin-seven .jw-progress{background:#ff0046}.jw-skin-seven .jw-knob{width:.6em;height:.6em;background-color:#fff;box-shadow:0 0 0 1px #000;border-radius:1em}.jw-skin-seven .jw-slider-horizontal .jw-slider-container{height:.95em}.jw-skin-seven .jw-slider-horizontal .jw-rail,.jw-skin-seven .jw-slider-horizontal .jw-buffer,.jw-skin-seven .jw-slider-horizontal .jw-progress{height:.2em;border-radius:0}.jw-skin-seven .jw-slider-horizontal .jw-knob{top:-0.19999999999999998em}.jw-skin-seven .jw-slider-horizontal .jw-cue{top:-0.04999999999999999em;width:.3em;height:.3em;background-color:#fff;border-radius:50%}.jw-skin-seven .jw-slider-vertical .jw-rail,.jw-skin-seven .jw-slider-vertical .jw-buffer,.jw-skin-seven .jw-slider-vertical .jw-progress{width:.2em}.jw-skin-seven .jw-slider-vertical .jw-knob{margin-bottom:-0.3em}.jw-skin-seven .jw-volume-tip{width:100%;left:-45%;padding-bottom:.7em}.jw-skin-seven .jw-text-duration{color:#666f82}.jw-skin-seven .jw-controlbar-right-group .jw-icon-tooltip:before,.jw-skin-seven .jw-controlbar-right-group .jw-icon-inline:before{border-left:1px solid #666}.jw-skin-seven .jw-controlbar-right-group .jw-icon-inline:first-child:before{border:0}.jw-skin-seven .jw-dock .jw-dock-button{border-radius:50%;border:1px solid #333}.jw-skin-seven .jw-dock .jw-overlay{border-radius:2.5em}.jw-skin-seven .jw-icon-tooltip .jw-active-option{background-color:#ff0046;color:#fff}.jw-skin-seven .jw-icon-volume{min-width:2.6em}.jw-skin-seven .jw-time-tip,.jw-skin-seven .jw-menu,.jw-skin-seven .jw-volume-tip,.jw-skin-seven .jw-skip{border:1px solid #333}.jw-skin-seven .jw-time-tip{padding:.2em;bottom:1.3em}.jw-skin-seven .jw-menu,.jw-skin-seven .jw-volume-tip{bottom:.24em}.jw-skin-seven .jw-skip{padding:.4em;border-radius:1.75em}.jw-skin-seven .jw-skip .jw-text,.jw-skin-seven .jw-skip .jw-icon-inline{color:#fff;line-height:1.75em}.jw-skin-seven .jw-skip.jw-skippable:hover .jw-text,.jw-skin-seven .jw-skip.jw-skippable:hover .jw-icon-inline{color:#ff0046}.jw-skin-seven.jw-flag-touch .jw-controlbar .jw-icon:before,.jw-skin-seven.jw-flag-touch .jw-text-elapsed,.jw-skin-seven.jw-flag-touch .jw-text-duration{padding:0 .35em}.jw-skin-seven.jw-flag-touch .jw-controlbar .jw-icon-prev:before{padding:0 .125em 0 .7em}.jw-skin-seven.jw-flag-touch .jw-controlbar .jw-icon-next:before{padding:0 .7em 0 .125em}.jw-skin-seven.jw-flag-touch .jw-controlbar .jw-icon-playlist:before{padding:0 .225em}
|
||||
1
server/webplatform/www/jwplayer/skins/six.css
Normal file
1
server/webplatform/www/jwplayer/skins/six.css
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/skins/stormtrooper.css
Normal file
1
server/webplatform/www/jwplayer/skins/stormtrooper.css
Normal file
File diff suppressed because one or more lines are too long
1
server/webplatform/www/jwplayer/skins/vapor.css
Normal file
1
server/webplatform/www/jwplayer/skins/vapor.css
Normal file
@ -0,0 +1 @@
|
||||
.jw-icon{font-family:'jw-icons';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;text-transform:none;background-color:transparent;font-variant:normal;-webkit-font-feature-settings:"liga";-moz-font-feature-settings:"liga=1";-moz-font-feature-settings:"liga";-ms-font-feature-settings:"liga" 1;-o-font-feature-settings:"liga";font-feature-settings:"liga";-moz-osx-font-smoothing:grayscale}.jw-skin-vapor .jw-background-color{background:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-controlbar{background:rgba(255,255,255,0.4)}.jw-skin-vapor .jw-text{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-tooltip-title{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-knob{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-button-color{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-button-color:hover{color:#fff}.jw-skin-vapor .jw-toggle{color:#fff}.jw-skin-vapor .jw-toggle.jw-off{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-option{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-option.jw-active-option{color:#fff}.jw-skin-vapor .jw-icon-display{color:rgba(255,255,255,0.5)}.jw-skin-vapor .jw-display-icon-container{border-radius:.5em}.jw-skin-vapor .jw-display-icon-container:hover{background:#000}.jw-skin-vapor .jw-display-icon-container:hover .jw-icon-display{color:#0f9e60}.jw-skin-vapor .jw-rail{background:rgba(255,255,255,0.4)}.jw-skin-vapor .jw-buffer{background:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-progress{background:#0f9e60}.jw-skin-vapor .jw-slider-horizontal{background:rgba(255,255,255,0.4)}.jw-skin-vapor .jw-slider-horizontal .jw-knob{margin-left:-0.325em}.jw-skin-vapor .jw-slider-vertical .jw-knob{margin-bottom:-0.325em}.jw-skin-vapor .jw-time-tip,.jw-skin-vapor .jw-volume-tip,.jw-skin-vapor .jw-menu{background:rgba(0,0,0,0.5);border:0;padding:.5em}.jw-skin-vapor .jw-skip{background:rgba(255,255,255,0.4);padding:.5em}.jw-skin-vapor .jw-skip .jw-skip-icon{color:rgba(0,0,0,0.5)}.jw-skin-vapor .jw-skip.jw-skippable:hover .jw-skip-icon,.jw-skin-vapor .jw-skip.jw-skippable:hover .jw-text{color:#fff}.jw-skin-vapor .jw-time-tip .jw-text,.jw-skin-vapor .jw-dock-button .jw-text{color:#bbb}.jw-skin-vapor .jw-time-tip{bottom:1em}.jw-skin-vapor .jw-dock-button{background:rgba(0,0,0,0.5);border-radius:.5em}.jw-skin-vapor .jw-dock-button:hover{background:#000}.jw-skin-vapor .jw-playlist-container{padding:0}.jw-skin-vapor .jw-icon-inline,.jw-skin-vapor .jw-icon-tooltip,.jw-skin-vapor .jw-text-elapsed,.jw-skin-vapor .jw-text-duration{padding:0 .25em}.jw-skin-vapor .jw-time-tip,.jw-skin-vapor .jw-volume-tip,.jw-skin-vapor .jw-menu{border-radius:.25em;bottom:.3em}.jw-skin-vapor .jw-skip{border-radius:.25em}.jw-skin-vapor .jw-option{color:#fff}.jw-skin-vapor .jw-option:hover,.jw-skin-vapor .jw-option.jw-active-option{color:#0f9e60}.jw-skin-vapor .jw-playlist-container{left:-42%;bottom:0;border-radius:0;background-color:#1e1e1e}.jw-skin-vapor .jw-playlist-container .jw-option,.jw-skin-vapor .jw-playlist-container .jw-text,.jw-skin-vapor .jw-playlist-container .jw-icon{color:#a0a0a0}.jw-skin-vapor .jw-playlist-container .jw-option{border-bottom:1px solid #000;background-color:#1e1e1e;color:#a8a8a8}.jw-skin-vapor .jw-playlist-container .jw-option:hover,.jw-skin-vapor .jw-playlist-container .jw-option.jw-active-option{color:#0f9e60}.jw-skin-vapor .jw-playlist-container ::-webkit-scrollbar-track{background-color:#000}.jw-skin-vapor .jw-playlist-container ::-webkit-scrollbar{width:2px;border:10px solid #1e1e1e}.jw-skin-vapor .jw-playlist-container ::-webkit-scrollbar-thumb{background-color:#a0a0a0}.jw-skin-vapor .jw-tooltip-title{border-bottom:1px solid #000;background-color:#1e1e1e}.jw-skin-vapor .jw-slider-horizontal{height:2em}.jw-skin-vapor .jw-slider-horizontal .jw-slider-container{height:2em}.jw-skin-vapor .jw-slider-horizontal .jw-rail,.jw-skin-vapor .jw-slider-horizontal .jw-progress,.jw-skin-vapor .jw-slider-horizontal .jw-buffer{height:2em}.jw-skin-vapor .jw-slider-horizontal .jw-knob,.jw-skin-vapor .jw-slider-horizontal .jw-cue{height:2em}.jw-skin-vapor .jw-slider-horizontal .jw-knob{margin-left:0;background-color:#fff;width:.2em}.jw-skin-vapor .jw-slider-horizontal .jw-cue{top:.6699999999999999em;background:rgba(255,255,255,0.5);height:.66em}.jw-skin-vapor .jw-slider-vertical{padding:.4em;bottom:3px;border-radius:2px;border:0}.jw-skin-vapor .jw-slider-vertical .jw-knob{display:none}.jw-skin-vapor .jw-slider-vertical .jw-rail{background-color:rgba(0,0,0,0.8)}.jw-skin-vapor .jw-slider-vertical .jw-rail,.jw-skin-vapor .jw-slider-vertical .jw-progress{width:.5em;border:1px solid #000}.jw-skin-vapor .jw-icon-cc.jw-off:before{content:"\e604"}.jw-skin-vapor .jw-icon-hd.jw-off:before{content:"\e609"}.jw-skin-vapor.jw-flag-audio-player .jw-controlbar{background:rgba(0,0,0,0.5)}
|
||||
Reference in New Issue
Block a user