This commit is contained in:
KimLS
2017-01-22 22:26:34 -08:00
parent cd4d79c02b
commit 40edbc3b64
48 changed files with 82834 additions and 9 deletions
+1 -1
View File
@@ -132,7 +132,7 @@ void EQApplicationPacket::build_header_dump(char *buffer) const
#ifdef STATIC_OPCODE #ifdef STATIC_OPCODE
sprintf(buffer, "[OpCode 0x%04x Size=%u]\n", emu_opcode,size); sprintf(buffer, "[OpCode 0x%04x Size=%u]\n", emu_opcode,size);
#else #else
sprintf(buffer, "[OpCode %s Size=%u]",OpcodeManager::EmuToName(emu_opcode),size); sprintf(buffer, "[OpCode %s(0x%04x) Size=%u]",OpcodeManager::EmuToName(emu_opcode), GetProtocolOpcode(), size);
#endif #endif
} }
+3
View File
@@ -118,8 +118,11 @@ public:
uint16 GetOpcodeBypass() const { return opcode_bypass; } uint16 GetOpcodeBypass() const { return opcode_bypass; }
void SetOpcodeBypass(uint16 v) { opcode_bypass = v; } void SetOpcodeBypass(uint16 v) { opcode_bypass = v; }
uint16 GetProtocolOpcode() const { return protocol_opcode; }
void SetProtocolOpcode(uint16 v) { protocol_opcode = v; }
protected: protected:
uint16 protocol_opcode;
uint8 app_opcode_size; uint8 app_opcode_size;
uint16 opcode_bypass; uint16 opcode_bypass;
private: private:
+1
View File
@@ -120,6 +120,7 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() {
EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode); EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode);
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->m_options.opcode_size, p->Length() - m_owner->m_options.opcode_size); EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->m_options.opcode_size, p->Length() - m_owner->m_options.opcode_size);
ret->SetProtocolOpcode(opcode);
m_packet_queue.pop_front(); m_packet_queue.pop_front();
return ret; return ret;
} }
+24
View File
@@ -0,0 +1,24 @@
var auth = require('../../core/jwt_auth.js').auth;
var sql = require('./sql.js');
var RegisterEndpoint = function(app, api, single_name, plural_name, pkey) {
app.get('/api/data/' + single_name + '/:' + pkey, auth, function (req, res) {
sql.Retrieve(req, res, plural_name, pkey);
});
app.put('/api/data/' + single_name + '/:' + pkey, auth, function (req, res) {
sql.CreateUpdate(req, res, plural_name, pkey);
});
app.delete('/api/data/' + single_name + '/:' + pkey, auth, function (req, res) {
sql.Delete(req, res, plural_name, pkey);
});
app.post('/api/data/' + single_name + '/search', auth, function (req, res) {
sql.Search(req, res, plural_name, pkey, res);
});
};
module.exports = {
'Register': RegisterEndpoint
}
+9
View File
@@ -0,0 +1,9 @@
var endpoint = require('./endpoint.js');
var RegisterAPI = function(app, api) {
endpoint.Register(app, api, 'item', 'items', 'id');
};
module.exports = {
'Register': RegisterAPI
}
+340
View File
@@ -0,0 +1,340 @@
var moment = require('moment');
function CreateReplace(table, body, fields) {
try {
var query = 'REPLACE INTO ' + table + ' VALUES(';
var first = true;
var args = [];
for(var idx in fields) {
if(first) {
first = false;
} else {
query += ',';
}
query += '?';
var entry = fields[idx];
if(entry.type === 12) {
try {
var d = new moment(body[entry.name]);
if(d.isValid()) {
args.push(d.format('YYYY-MM-DD HH:mm:ss'));
} else {
args.push(null);
}
} catch(ex) {
args.push(null);
}
} else {
args.push(body[entry.name]);
}
}
query += ')';
return { 'query': query, 'args': args };
} catch(ex) {
return { 'query': '', 'args': [] };
}
}
function CreateUpdate(req, res, table, pkey) {
req.mysql.getConnection(function(err, connection) {
try {
if(err) {
console.log(err);
connection.release();
res.sendStatus(500);
return;
}
if(req.body[pkey] !== parseInt(req.params[pkey], 10)) {
connection.release();
res.sendStatus(400);
return;
}
connection.query('SELECT * FROM ' + table + ' WHERE ' + pkey + '=? LIMIT 1', [req.params[pkey]], function (error, results, fields) {
try {
if(error) {
console.log(error);
connection.release();
res.sendStatus(400);
return;
}
var replace = CreateReplace(table, req.body, fields);
if(replace.query === '') {
connection.release();
res.sendStatus(400);
return;
}
connection.query(replace.query, replace.args, function(error, results, fields) {
try {
if(error) {
console.log(error);
connection.release();
res.sendStatus(400);
return;
}
connection.release();
res.sendStatus(200);
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
}
function Retrieve(req, res, table, pkey) {
req.mysql.getConnection(function(err, connection) {
try {
if(err) {
console.log(err);
connection.release();
res.sendStatus(500);
return;
}
connection.query('SELECT * FROM ' + table + ' WHERE ' + pkey + '=? LIMIT 1', [req.params[pkey]], function (error, results, fields) {
try {
if(results.length == 0) {
connection.release();
res.sendStatus(404);
return;
}
var result = results[0];
var ret = { };
for(var idx in result) {
var value = result[idx];
ret[idx] = value;
}
connection.release();
res.json(ret);
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
}
function Delete(req, res, table, pkey) {
req.mysql.getConnection(function(err, connection) {
try {
if(err) {
console.log(err);
connection.release();
res.sendStatus(500);
return;
}
connection.query('DELETE FROM ' + table + ' WHERE ' + pkey + '=? LIMIT 1', [req.params[pkey]], function (error, results, fields) {
try {
if(error) {
console.log(error);
connection.release();
res.sendStatus(400);
return;
}
connection.release();
res.sendStatus(200);
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
}
function Search(req, res, table, pkey) {
//Verify incoming model
if(!req.body.hasOwnProperty('draw')) {
res.sendStatus(400);
return;
}
if(!req.body.hasOwnProperty('start')) {
res.sendStatus(400);
return;
}
if(!req.body.hasOwnProperty('length')) {
res.sendStatus(400);
return;
}
if(!req.body.hasOwnProperty('search')) {
res.sendStatus(400);
return;
}
if(!req.body.hasOwnProperty('columns')) {
res.sendStatus(400);
return;
}
if(!req.body.hasOwnProperty('order')) {
res.sendStatus(400);
return;
}
req.mysql.getConnection(function(err, connection) {
try {
if(err) {
console.log(err);
connection.release();
res.sendStatus(500);
return;
}
var ret = { };
ret.draw = req.body['draw'];
ret.data = [];
var query = 'SELECT ';
var idx;
var args = [];
var first = true;
for(idx in req.body['columns']) {
var column = req.body['columns'][idx];
if(first) {
first = false;
} else {
query += ', ';
}
query += connection.escapeId(column.data);
}
query += ' FROM ' + table;
first = true;
for(idx in req.body['order']) {
var order = req.body['order'][idx];
if(first) {
query += ' ORDER BY ';
first = false;
} else {
query += ', ';
}
var column = req.body['columns'][order.column];
query += connection.escapeId(column.data);
if(order.dir === 'asc') {
query += ' ASC';
} else {
query += ' DESC';
}
}
connection.query(query, args, function (error, results, fields) {
try {
if(error) {
console.log(error);
connection.release();
res.sendStatus(400);
return;
}
ret.recordsTotal = results.length;
for(var result_idx in results) {
var result = results[result_idx];
if(req.body['search'].value && req.body['search'].value.length > 0) {
var found = false;
for(idx in req.body['columns']) {
var column = req.body['columns'][idx];
if(column.searchable) {
if(String(result[column.data]).toLowerCase().includes(String(req.body['search'].value).toLowerCase())) {
found = true;
break;
}
}
}
if(found) {
var obj = { };
for(var i in result) {
var value = result[i];
obj[i] = value;
}
ret.data.push(obj);
}
} else {
var obj = { };
for(var i in result) {
var value = result[i];
obj[i] = value;
}
ret.data.push(obj);
}
}
ret.recordsFiltered = ret.data.length;
ret.data = ret.data.slice(req.body['start'], req.body['start'] + req.body['length']);
connection.release();
res.json(ret);
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
} catch(ex) {
console.log(ex);
connection.release();
res.sendStatus(500);
}
});
}
module.exports = {
'CreateUpdate': CreateUpdate,
'Retrieve': Retrieve,
'Delete': Delete,
'Search': Search,
}
+9
View File
@@ -0,0 +1,9 @@
var RegisterAPI = function(app, api) {
require('./eqw.js').Register(app, api);
require('./token.js').Register(app);
require('./data').Register(app, api);
};
module.exports = {
'Register': RegisterAPI
}
+8 -4
View File
@@ -30,6 +30,12 @@ api.Init(settings.servertalk.addr, settings.servertalk.port, false, settings.ser
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
//make sure all routes can see our injected dependencies //make sure all routes can see our injected dependencies
app.use(function (req, res, next) { app.use(function (req, res, next) {
req.servertalk = api; req.servertalk = api;
@@ -42,10 +48,8 @@ app.get('/', function (req, res) {
res.send({ status: "online" }); res.send({ status: "online" });
}); });
require('./http/token.js').Register(app); require('./http').Register(app, api);
require('./http/eqw.js').Register(app, api); require('./ws').Register(wsi, api);
//require('./ws/token.js').Register(app);
require('./ws/eqw.js').Register(wsi, api);
server.on('request', app); server.on('request', app);
server.listen(settings.port, function () { console.log('Listening on ' + server.address().port) }); server.listen(settings.port, function () { console.log('Listening on ' + server.address().port) });
+3 -3
View File
@@ -11,15 +11,15 @@ class ServertalkAPI
var self = this; var self = this;
this.client.on('connecting', function() { this.client.on('connecting', function() {
console.log('Connecting...'); //console.log('Connecting...');
}); });
this.client.on('connect', function(){ this.client.on('connect', function(){
console.log('Connected'); //console.log('Connected');
}); });
this.client.on('close', function(){ this.client.on('close', function(){
console.log('Closed'); //console.log('Closed');
}); });
this.client.on('error', function(err){ this.client.on('error', function(err){
+2
View File
@@ -11,10 +11,12 @@
"dependencies": { "dependencies": {
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
"express": "^4.14.0", "express": "^4.14.0",
"hammerjs": "^2.0.8",
"jsonwebtoken": "^7.2.1", "jsonwebtoken": "^7.2.1",
"libsodium": "^0.4.8", "libsodium": "^0.4.8",
"libsodium-wrappers": "^0.4.8", "libsodium-wrappers": "^0.4.8",
"libsodium-wrappers-sumo": "^0.4.8", "libsodium-wrappers-sumo": "^0.4.8",
"moment": "^2.17.1",
"mysql": "^2.12.0", "mysql": "^2.12.0",
"node-uuid": "^1.4.7", "node-uuid": "^1.4.7",
"ws": "^1.1.1" "ws": "^1.1.1"
+47
View File
@@ -0,0 +1,47 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
+3
View File
@@ -0,0 +1,3 @@
{
"api_url": "http://localhost:9080"
}
+13
View File
@@ -0,0 +1,13 @@
.login-panel {
width: 400px;
padding: 28px; }
.login-title {
margin: 3em 0 3em 0; }
.login-error-message {
color: #ff2828;
padding: 8px; }
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="Web portal for EQEmu WI Front">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>EQEmu WI Front</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700">
<link rel="stylesheet" href="css/vendor.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<app-root>Loading...</app-root>
<script type="text/javascript" src="js/bundle.js"></script>
<script type="text/javascript" src="js/templates.js"></script>
</body>
</html>
+76151
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4
View File
@@ -0,0 +1,4 @@
angular.module('templates', []).run(['$templateCache', function($templateCache) {$templateCache.put('index.html','<!DOCTYPE html>\r\n<html>\r\n\t<head>\r\n\t\t<meta charset="utf-8">\r\n\t\t<meta http-equiv="X-UA-Compatible" content="IE=edge">\r\n\t\t<meta name="description" content="Web portal for EQEmu WI Front">\r\n\t\t<meta name="viewport" content="width=device-width, initial-scale=1">\r\n\t\t<title>EQEmu WI Front</title>\r\n\r\n\t\t<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700">\r\n <link rel="stylesheet" href="css/vendor.css">\r\n\t\t<link rel="stylesheet" href="css/app.css">\r\n\t</head>\r\n\t<body>\r\n <app-root>Loading...</app-root>\r\n\t\t<script type="text/javascript" src="js/bundle.js"></script>\r\n <script type="text/javascript" src="js/templates.js"></script>\r\n\t</body>\r\n</html>\r\n');
$templateCache.put('app/app.html','<ui-view layout-fill></ui-view>');
$templateCache.put('app/components/login/login.html','<md-content layout-fill layout="column" layout-align="start center">\r\n <h2 class="login-title">Login</h2>\r\n <form layout="column" class="md-whiteframe-4dp login-panel" ng-submit="$ctrl.doLogin()">\r\n <md-input-container class="md-block">\r\n <label>Username</label>\r\n <input name="username" required ng-model="$ctrl.username" ng-disabled="$ctrl.loggingIn" aria-label="Username">\r\n </md-input-container>\r\n\r\n <md-input-container class="md-block">\r\n <label>Password</label>\r\n <input type="password" name="password" required ng-model="$ctrl.password" ng-disabled="$ctrl.loggingIn" aria-label="Password">\r\n </md-input-container>\r\n\r\n <div layout="row">\r\n <md-checkbox ng-model="$ctrl.rememberMe" ng-disabled="$ctrl.loggingIn" aria-label="Remember Me">Remember Me</md-checkbox>\r\n </div>\r\n\r\n <span class="login-error-message" ng-show="$ctrl.error">\r\n Unauthorized login.\r\n </span>\r\n\r\n <md-button type="submit" class="md-raised md-primary" ng-disabled="!$ctrl.canLogin()">Login</md-button>\r\n </form>\r\n</md-content>\r\n');
$templateCache.put('app/components/portal/portal.html','<md-content layout-fill>\r\n <md-toolbar class="md-hue-2">\r\n <div class="md-toolbar-tools">\r\n <md-button class="md-icon-button" aria-label="menu">\r\n <md-icon class="mdi mdi-menu mdi-24px"></md-icon>\r\n </md-button>\r\n <h2>\r\n <span>EQEmu WI Portal</span>\r\n </h2>\r\n <span flex></span>\r\n <md-menu md-offset="-20 -20">\r\n <md-button class="md-icon-button" aria-label="More" ng-click="$ctrl.openMenu($mdOpenMenu, $event)">\r\n <md-icon md-menu-origin class="mdi mdi-dots-vertical mdi-24px"></md-icon>\r\n </md-button>\r\n <md-menu-content width="4">\r\n <md-menu-item>\r\n <md-button ng-click="$ctrl.logout($event)">\r\n <md-iconclass="mdi mdi-power mdi-24px" md-menu-align-target></md-icon>\r\n Logout\r\n </md-button>\r\n </md-menu-item>\r\n </md-menu-content>\r\n </md-menu>\r\n </div>\r\n </md-toolbar>\r\n</md-content>');}]);
+209
View File
@@ -0,0 +1,209 @@
'use strict';
var del = require('del');
var fs = require('fs');
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var gutil = require('gulp-util');
var concat = require('gulp-concat');
var connect = require('gulp-connect');
var templateCache = require('gulp-angular-templatecache');
var minifyCSS = require('gulp-cssnano');
var minifyHTML = require('gulp-htmlmin');
var sass = require('gulp-sass');
var gulpsync = require('gulp-sync')(gulp);
gulp.task('clean:css', function() {
return del([
'dist/css/**/*'
]);
});
gulp.task('clean:javascript', function() {
return del([
'dist/js/**/*'
]);
});
gulp.task('clean', ['clean:css', 'clean:javascript']);
gulp.task('app:javascript:prod', function () {
var b = browserify({
entries: 'src/index.js',
debug: false
});
return b.transform('babelify', {presets: ["es2015"]})
.transform('brfs')
.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist/js/'))
.pipe(connect.reload());
});
gulp.task('app:javascript:dev', function () {
var b = browserify({
entries: 'src/index.js',
debug: true
});
return b.transform('babelify', {presets: ["es2015"]})
.transform('brfs')
.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.on('error', gutil.log)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./dist/js/'))
.pipe(connect.reload());
});
gulp.task('javascript:dev', ['app:javascript:dev']);
gulp.task('javascript:prod', ['app:javascript:prod']);
var vendor_css = [
'node_modules/angular-material/angular-material.min.css',
'node_modules/angular-loading-bar/build/loading-bar.min.css',
'node_modules/mdi/css/materialdesignicons.min.css'
];
gulp.task('vendor:css:prod', function() {
return gulp.src(vendor_css)
.pipe(minifyCSS())
.pipe(concat('vendor.css'))
.pipe(gulp.dest('dist/css'))
.pipe(connect.reload());
});
gulp.task('vendor:css:dev', function() {
return gulp.src(vendor_css)
.pipe(concat('vendor.css'))
.pipe(gulp.dest('dist/css'))
.pipe(connect.reload());
});
var app_sass = [
'src/**/*.scss',
];
gulp.task('app:sass:prod', function() {
return gulp.src(app_sass)
.pipe(sass().on('error', sass.logError))
.pipe(minifyCSS())
.pipe(concat('app.css'))
.pipe(gulp.dest('dist/css'))
.pipe(connect.reload());
});
gulp.task('app:sass:dev', function() {
return gulp.src(app_sass)
.pipe(sass().on('error', sass.logError))
.pipe(concat('app.css'))
.pipe(gulp.dest('dist/css'))
.pipe(connect.reload());
});
gulp.task('css:prod', ['vendor:css:prod', 'app:sass:prod']);
gulp.task('css:dev', ['vendor:css:dev', 'app:sass:dev']);
var assets_images = [
'src/assets/images/**/*',
];
var assets_media = [
'src/assets/media/*',
];
gulp.task('assets:images', function() {
return gulp.src(assets_images)
.pipe(gulp.dest('dist/images'))
.pipe(connect.reload());
});
gulp.task('assets:media', function() {
return gulp.src(assets_media)
.pipe(gulp.dest('dist/media'))
.pipe(connect.reload());
});
var assets_fonts = [
'node_modules/mdi/fonts/*'
];
gulp.task('assets:fonts', function() {
return gulp.src(assets_fonts)
.pipe(gulp.dest('dist/fonts'));
});
gulp.task('assets', ['assets:images', 'assets:media', 'assets:fonts']);
var app_html = [
'src/**/*.html'
];
gulp.task('app:html:prod', function() {
return gulp.src(app_html)
.pipe(minifyHTML({collapseWhitespace: true, removeComments: true}))
.pipe(templateCache({standalone: true}))
.pipe(gulp.dest('dist/js'))
.pipe(connect.reload());
});
gulp.task('app:html:dev', function() {
return gulp.src(app_html)
.pipe(templateCache({standalone: true}))
.pipe(gulp.dest('dist/js'))
.pipe(connect.reload());
});
var app_entry = [
'src/index.html'
];
gulp.task('app:entry:prod', function() {
return gulp.src(app_entry)
.pipe(minifyHTML({collapseWhitespace: true, removeComments: true}))
.pipe(gulp.dest('dist'))
.pipe(connect.reload());
});
gulp.task('app:entry:dev', function() {
return gulp.src(app_entry)
.pipe(gulp.dest('dist'))
.pipe(connect.reload());
});
gulp.task('build:prod', gulpsync.sync(['clean', 'javascript:prod', 'css:prod', 'app:html:prod', 'app:entry:prod', 'assets']));
gulp.task('build:dev', gulpsync.sync(['clean', 'javascript:dev', 'css:dev', 'app:html:dev', 'app:entry:dev', 'assets']));
gulp.task('build', ['build:prod']);
gulp.task('live_reload', function() {
connect.server({
livereload: true,
root: 'dist',
port: '8000'
});
});
gulp.task('watch', ['live_reload'], function() {
gulp.watch('src/**/*.js', ['app:javascript:dev']);
gulp.watch(vendor_css, ['vendor:css:dev']);
gulp.watch(app_sass, ['app:sass:dev']);
gulp.watch(assets_images, ['assets:images']);
gulp.watch(assets_media, ['assets:media']);
gulp.watch(assets_fonts, ['assets:fonts']);
gulp.watch(app_html, ['app:html:dev']);
gulp.watch(app_entry, ['app:entry:dev']);
});
gulp.task('serve', gulpsync.sync(['build:dev', 'watch']));
+42
View File
@@ -0,0 +1,42 @@
{
"name": "wi-front",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"devDependencies": {
"babel-preset-es2015": "^6.22.0",
"babelify": "^7.3.0",
"brfs": "^1.4.3",
"browserify": "^13.3.0",
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-angular-templatecache": "^2.0.0",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.0.0",
"gulp-cssnano": "^2.1.2",
"gulp-htmlmin": "^3.0.0",
"gulp-sass": "^3.1.0",
"gulp-sourcemaps": "^2.4.0",
"gulp-sync": "^0.1.4",
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.8",
"lodash": "^4.17.4",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
},
"dependencies": {
"angular": "^1.6.1",
"angular-animate": "^1.6.1",
"angular-aria": "^1.6.1",
"angular-loading-bar": "^0.9.0",
"angular-material": "^1.1.1",
"angular-ui-router": "^0.4.2",
"mdi": "^1.8.36",
"ngstorage": "^0.3.11"
}
}
+1
View File
@@ -0,0 +1 @@
<ui-view layout-fill></ui-view>
+15
View File
@@ -0,0 +1,15 @@
(function() {
'use strict';
var app = angular.module('app');
app.component('appRoot', {
templateUrl: 'app/app.html',
controller: ['$state', function($state) {
var self = this;
this.$onInit = function () {
};
}]
});
})();
View File
+6
View File
@@ -0,0 +1,6 @@
(function() {
'use strict';
require('./login/login.js');
require('./portal/portal.js');
})();
@@ -0,0 +1,24 @@
<md-content layout-fill layout="column" layout-align="start center">
<h2 class="login-title">Login</h2>
<form layout="column" class="md-whiteframe-4dp login-panel" ng-submit="$ctrl.doLogin()">
<md-input-container class="md-block">
<label>Username</label>
<input name="username" required ng-model="$ctrl.username" ng-disabled="$ctrl.loggingIn" aria-label="Username">
</md-input-container>
<md-input-container class="md-block">
<label>Password</label>
<input type="password" name="password" required ng-model="$ctrl.password" ng-disabled="$ctrl.loggingIn" aria-label="Password">
</md-input-container>
<div layout="row">
<md-checkbox ng-model="$ctrl.rememberMe" ng-disabled="$ctrl.loggingIn" aria-label="Remember Me">Remember Me</md-checkbox>
</div>
<span class="login-error-message" ng-show="$ctrl.error">
Unauthorized login.
</span>
<md-button type="submit" class="md-raised md-primary" ng-disabled="!$ctrl.canLogin()">Login</md-button>
</form>
</md-content>
@@ -0,0 +1,52 @@
(function() {
'use strict';
var app = angular.module('app');
app.component('login', {
templateUrl: 'app/components/login/login.html',
controller: ['$state', 'appConfig', 'loginState', '$http', function($state, appConfig, loginState, $http) {
var self = this;
self.username = '';
self.password = '';
self.rememberMe = false;
self.doLogin = doLogin;
self.canLogin = canLogin;
self.loggingIn = false;
self.error = false;
function doLogin() {
if(!canLogin()) {
return;
}
self.loggingIn = true;
self.error = false;
var data = { username: self.username, password: self.password };
$http.post(appConfig.config.api_url + '/api/token', data)
.then(function(response) {
self.loggingIn = false;
loginState.login(self.username, response.data, self.rememberMe);
}, function(response) {
self.loggingIn = false;
self.error = true;
});
}
function canLogin() {
if(self.username.length === 0 || self.password.length === 0 || self.loggingIn) {
return false;
}
return true;
}
self.$onInit = function () {
//If logged in just goto the next state
if(loginState.isLoggedIn()) {
$state.go(loginState.nextState, loginState.nextStateParams);
};
};
}]
});
})();
@@ -0,0 +1,16 @@
.login-panel
{
width: 400px;
padding: 28px;
}
.login-title
{
margin: 3em 0 3em 0;
}
.login-error-message
{
color: rgba(255, 40, 40, 200);
padding: 8px;
}
@@ -0,0 +1,26 @@
<md-content layout-fill>
<md-toolbar class="md-hue-2">
<div class="md-toolbar-tools">
<md-button class="md-icon-button" aria-label="menu">
<md-icon class="mdi mdi-menu mdi-24px"></md-icon>
</md-button>
<h2>
<span>EQEmu WI Portal</span>
</h2>
<span flex></span>
<md-menu md-offset="-20 -20">
<md-button class="md-icon-button" aria-label="More" ng-click="$ctrl.openMenu($mdOpenMenu, $event)">
<md-icon md-menu-origin class="mdi mdi-dots-vertical mdi-24px"></md-icon>
</md-button>
<md-menu-content width="4">
<md-menu-item>
<md-button ng-click="$ctrl.logout($event)">
<md-iconclass="mdi mdi-power mdi-24px" md-menu-align-target></md-icon>
Logout
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</div>
</md-toolbar>
</md-content>
@@ -0,0 +1,39 @@
(function() {
'use strict';
var app = angular.module('app');
app.component('portal', {
templateUrl: 'app/components/portal/portal.html',
controller: ['$state', '$mdDialog', 'loginState', function($state, $mdDialog, loginState) {
var self = this;
self.openMenu = openMenu;
self.logout = logout;
function openMenu($mdOpenMenu, ev) {
self.originatorEv = ev;
$mdOpenMenu(ev);
};
function logout(ev) {
var confirm = $mdDialog.confirm()
.title('Logout')
.textContent('Are you sure you wish to logout?')
.ariaLabel('Logout')
.targetEvent(ev)
.ok('Logout')
.cancel('Cancel');
$mdDialog.show(confirm).then(function() {
loginState.logout();
$state.go('login');
}, function() {
});
}
self.$onInit = function () {
};
}]
});
})();
@@ -0,0 +1,24 @@
(function(){
'use strict';
var app = angular.module('app');
app.factory('applyAuthIntercept', ['$injector', function($injector) {
return {
request: function(config) {
if(config.anonOnly) {
return config;
}
if(!config.headers) {
config.headers = { };
}
var loginState = $injector.get('loginState');
config.headers.Authorization = 'Bearer ' + loginState.token;
return config;
}
};
}]);
})();
@@ -0,0 +1,25 @@
(function(){
'use strict';
var app = angular.module('app');
app.factory('checkAuthIntercept', ['$q', '$injector', function($q, $injector) {
return {
responseError: function(response) {
if(response.status === 401) {
var $state = $injector.get('$state');
var loginState = $injector.get('loginState');
if($state.current.name !== 'login') {
loginState.nextState = $state.current.name;
loginState.nextStateParams = {};
loginState.logout();
$state.go('login');
}
}
return $q.reject(response);
}
};
}]);
})();
@@ -0,0 +1,6 @@
(function() {
'use strict';
require('./apply-auth.js');
require('./check-auth.js');
})();
+21
View File
@@ -0,0 +1,21 @@
(function() {
'use strict';
var app = angular.module('app');
app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
$stateProvider.state('login', {
url: '/login',
template: '<login></login>'
});
$stateProvider.state('portal', {
url: '/portal',
template: '<portal></portal>'
});
}
]);
})();
+5
View File
@@ -0,0 +1,5 @@
(function() {
'use strict';
require('./core.js');
})();
+10
View File
@@ -0,0 +1,10 @@
(function() {
'use strict';
var fs = require('fs');
var app = angular.module('app');
app.service('appConfig', function() {
this.config = JSON.parse(fs.readFileSync(__dirname + '/../../../config.json', 'utf8'));
});
})();
+6
View File
@@ -0,0 +1,6 @@
(function() {
'use strict';
require('./config.js');
require('./login.js');
})();
+78
View File
@@ -0,0 +1,78 @@
(function() {
'use strict';
var app = angular.module('app');
app.service('loginState', ['$rootScope', '$http', '$httpParamSerializer', '$state', '$localStorage', '$sessionStorage',
function($rootScope, $http, $httpParamSerializer, $state, $localStorage, $sessionStorage) {
var self = this;
self.isLoggedIn = isLoggedIn;
self.logout = logout;
self.login = login;
self.nextState = 'portal';
self.nextStateParams = { };
self.token = '';
function isLoggedIn() {
var storage_bucket = null;
var token = null;
if($localStorage.token) {
storage_bucket = $localStorage;
token = $localStorage.token;
} else if($sessionStorage.token) {
storage_bucket = $sessionStorage;
token = $sessionStorage.token;
}
if(token) {
var expires = storage_bucket.expires;
var username = storage_bucket.username;
var expire_date = new Date(expires);
var current_date = new Date();
if(current_date > expire_date) {
self.logout();
} else {
self.token = token;
self.expires = expires;
self.username = username;
return true;
}
}
return false;
}
function logout() {
delete $localStorage.token;
delete $localStorage.expires;
delete $localStorage.username;
delete $sessionStorage.token;
delete $sessionStorage.expires;
delete $sessionStorage.username;
self.wasLoggedInAs = self.username;
self.username = null;
self.token = null;
self.expires = null;
}
function login(username, loginObj, rememberMe) {
self.username = username;
self.token = loginObj.token;
self.expires = loginObj.expires;
if(rememberMe) {
$localStorage.username = self.username;
$localStorage.token = self.token;
$localStorage.expires = self.expires;
} else {
$sessionStorage.username = self.username;
$sessionStorage.token = self.token;
$sessionStorage.expires = self.expires;
}
$state.go(self.nextState, self.nextStateParams);
}
}]);
})();
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="Web portal for EQEmu WI Front">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>EQEmu WI Front</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700">
<link rel="stylesheet" href="css/vendor.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<app-root>Loading...</app-root>
<script type="text/javascript" src="js/bundle.js"></script>
<script type="text/javascript" src="js/templates.js"></script>
</body>
</html>
+35
View File
@@ -0,0 +1,35 @@
var angular = require('angular');
require('angular-material');
require('angular-ui-router');
require('angular-loading-bar');
require('angular-animate');
require('ngstorage');
var app = angular.module('app', ['ngMaterial', 'ui.router', 'angular-loading-bar', 'ngAnimate' ,'ngStorage', 'templates']);
app.config(['$sceDelegateProvider', 'cfpLoadingBarProvider', '$animateProvider', '$compileProvider', '$localStorageProvider', '$sessionStorageProvider', '$httpProvider',
function($sceDelegateProvider, cfpLoadingBarProvider, $animateProvider, $compileProvider, $localStorageProvider, $sessionStorageProvider, $httpProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self'
]);
$animateProvider.classNameFilter(/^((?!(fa-spinner|fa-cog|fa-refresh|fa-circle-o-notch)).)*$/);
$compileProvider.preAssignBindingsEnabled(true);
$localStorageProvider.setKeyPrefix('eqemu_wi_');
$sessionStorageProvider.setKeyPrefix('eqemu_wi_');
$httpProvider.interceptors.push('applyAuthIntercept');
$httpProvider.interceptors.push('checkAuthIntercept');
}]);
angular.element(function() {
angular.bootstrap(document, ['app']);
});
require('./app/app.js');
require('./app/services');
require('./app/routes');
require('./app/components');
require('./app/interceptors');
View File
+7
View File
@@ -0,0 +1,7 @@
var RegisterAPI = function(wsi, api) {
require('./eqw.js').Register(wsi, api);
};
module.exports = {
'Register': RegisterAPI
}
+1 -1
View File
@@ -466,7 +466,7 @@ int Client::HandlePacket(const EQApplicationPacket *app)
args.push_back(const_cast<EQApplicationPacket*>(app)); args.push_back(const_cast<EQApplicationPacket*>(app));
parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args);
if (Log.log_settings[Logs::Client_Server_Packet_Unhandled].is_category_enabled == 1){ if (Log.log_settings[Logs::Client_Server_Packet_Unhandled].is_category_enabled == 1) {
char buffer[64]; char buffer[64];
app->build_header_dump(buffer); app->build_header_dump(buffer);
Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "%s %s", buffer, DumpPacketToString(app).c_str()); Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "%s %s", buffer, DumpPacketToString(app).c_str());