* Moved /tool and /webserver to under /src and added 'make tools' and 'make web-server'
* Removed ladmin compiling from 'make sql' git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1261 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
d8ebb246f6
commit
201bec5cd7
@ -1,5 +1,10 @@
|
||||
Date Added
|
||||
|
||||
03/21
|
||||
* Moved /tool and /webserver to under /src and added 'make tools' and 'make
|
||||
web-server' [celest]
|
||||
* Removed ladmin compiling from 'make sql' [celest]
|
||||
|
||||
03/20
|
||||
* Don't register the day/night timers if any one is set to 0 [celest]
|
||||
* Fixed @storage / @gstorage ATcommands thanks2 Yor/Freya [Lupus]
|
||||
|
19
Makefile
19
Makefile
@ -91,19 +91,26 @@ txt : src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map/
|
||||
|
||||
|
||||
ifdef SQLFLAG
|
||||
sql: src/common/GNUmakefile src/login_sql/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile src/ladmin/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile conf
|
||||
sql: src/common/GNUmakefile src/login_sql/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile conf
|
||||
cd src ; cd common ; $(MAKE) $(MKDEF) $@ ; cd ..
|
||||
cd src ; cd login_sql ; $(MAKE) $(MYLIB) $@ ; cd ..
|
||||
cd src ; cd char_sql ; $(MAKE) $(MYLIB) $@ ; cd ..
|
||||
cd src ; cd map ; $(MAKE) $(MYLIB) $@ ; cd ..
|
||||
cd src ; cd ladmin ; $(MAKE) $(MKDEF) $@ ; cd ..
|
||||
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MYLIB) $@ ; cd ..
|
||||
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MYLIB) $@ ; cd ..
|
||||
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MYLIB) ; cd ..
|
||||
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MYLIB) ; cd ..
|
||||
else
|
||||
sql:
|
||||
$(MAKE) CC="$(CC)" OPT="$(OPT)" SQLFLAG=1 $@
|
||||
endif
|
||||
|
||||
|
||||
tools:
|
||||
cd src ; cd tool && $(MAKE) $(MKDEF) && cd ..
|
||||
|
||||
webserver:
|
||||
cd src ; cd webserver && $(MAKE) $(MKDEF) && cd ..
|
||||
|
||||
|
||||
clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map/GNUmakefile src/ladmin/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile
|
||||
cd src ; cd common ; $(MAKE) $(MKDEF) $@ ; cd ..
|
||||
cd src ; cd login ; $(MAKE) $(MKDEF) $@ ; cd ..
|
||||
@ -115,10 +122,6 @@ clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map
|
||||
cd src ; cd txt-converter ; cd login ; $(MAKE) $(MKLIB) $@ ; cd ..
|
||||
cd src ; cd txt-converter ; cd char ; $(MAKE) $(MKLIB) $@ ; cd ..
|
||||
|
||||
tools:
|
||||
cd tool && $(MAKE) $(MKDEF) && cd ..
|
||||
$(CC) -o setupwizard setupwizard.c
|
||||
|
||||
src/common/GNUmakefile: src/common/Makefile
|
||||
sed -e 's/$$>/$$^/' src/common/Makefile > src/common/GNUmakefile
|
||||
src/login/GNUmakefile: src/login/Makefile
|
||||
|
6
src/tool/Makefile
Normal file
6
src/tool/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
all:
|
||||
$(CC) -o adduser adduser.c
|
||||
|
||||
clean:
|
||||
rm -f adduser
|
||||
rm -f *.exe
|
96
src/tool/adduser.c
Normal file
96
src/tool/adduser.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
This program adds an user to account.txt
|
||||
Don't usr it When login-sever is working.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *account_txt = "../save/account.txt";
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Function to suppress control characters in a string.
|
||||
//-----------------------------------------------------
|
||||
int remove_control_chars(unsigned char *str) {
|
||||
int i;
|
||||
int change = 0;
|
||||
|
||||
for(i = 0; str[i]; i++) {
|
||||
if (str[i] < 32) {
|
||||
str[i] = '_';
|
||||
change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
char username[24];
|
||||
char password[24];
|
||||
char sex[2];
|
||||
|
||||
int next_id, id;
|
||||
char line[1024];
|
||||
|
||||
// Check to see if account.txt exists.
|
||||
printf("Checking if '%s' file exists...\n", account_txt);
|
||||
FILE *FPaccin = fopen(account_txt, "r");
|
||||
if (FPaccin == NULL) {
|
||||
printf("'%s' file not found!\n", account_txt);
|
||||
printf("Run the setup wizard please.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
next_id = 2000000;
|
||||
while(fgets(line, sizeof(line)-1, FPaccin)) {
|
||||
if (line[0] == '/' && line[1] == '/') { continue; }
|
||||
if (sscanf(line, "%d\t%%newid%%\n", &id) == 1) {
|
||||
if (next_id < id) {
|
||||
next_id = id;
|
||||
}
|
||||
} else {
|
||||
sscanf(line,"%i%[^ ]", &id);
|
||||
if (next_id <= id) {
|
||||
next_id = id +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(FPaccin);
|
||||
printf("File exists.\n");
|
||||
|
||||
printf("Don't create an account if the login-server is online!!!\n");
|
||||
printf("If the login-server is online, press ctrl+C now to stop this software.\n");
|
||||
printf("\n");
|
||||
|
||||
strcpy(username, "");
|
||||
while (strlen(username) < 4 || strlen(username) > 23) {
|
||||
printf("Enter an username (4-23 characters): ");
|
||||
scanf("%s", &username);
|
||||
username[23] = 0;
|
||||
remove_control_chars(username);
|
||||
}
|
||||
|
||||
strcpy(password, "");
|
||||
while (strlen(password) < 4 || strlen(password) > 23) {
|
||||
printf("Enter a password (4-23 characters): ");
|
||||
scanf("%s", &password);
|
||||
password[23] = 0;
|
||||
remove_control_chars(password);
|
||||
}
|
||||
|
||||
strcpy(sex, "");
|
||||
while (strcmp(sex, "F") != 0 && strcmp(sex, "M") != 0) {
|
||||
printf("Enter a gender (M for male, F for female): ");
|
||||
scanf("%s", &sex);
|
||||
}
|
||||
|
||||
FILE *FPaccout = fopen(account_txt, "r+");
|
||||
fseek(FPaccout, 0, SEEK_END);
|
||||
fprintf(FPaccout, "%i %s %s - %s -\r\n", next_id, username, password, sex);
|
||||
close(FPaccout);
|
||||
|
||||
printf("Account added.\n");
|
||||
}
|
100
src/tool/backup
Normal file
100
src/tool/backup
Normal file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
##########################################################################
|
||||
# Athena用データバックアップツール
|
||||
#
|
||||
# Athenaの各種データファイル*.txtをバックアップするツール
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
# 設定方法
|
||||
# 実行する時のカレントフォルダからのデータへのパス、ファイルのリストを
|
||||
# 正しく設定します。バックアップ先のフォルダは自動作成されないので、
|
||||
# 自分で作成しておく必要があります。
|
||||
# フォルダの最後の「/」は省略できません。
|
||||
#
|
||||
# フォルダは引数でも指定できます。例>./backup ../save/ ./backup_data/
|
||||
# フォルダの最後の「/」は省略できません。
|
||||
#
|
||||
# 実行するとバックアップ先のフォルダへ、ファイル名に現在の日付と時刻を
|
||||
# つけてファイルをコピーします。
|
||||
#
|
||||
# * toolフォルダ内にbackup_dataフォルダを作成し、
|
||||
# athena.shの中に「./tool/backup ./save/ ./tool/backup_data/」
|
||||
# という行を追加すると、athenaを起動するたびにバックアップが取れます
|
||||
#
|
||||
# 復元するときは引数に「-r 日付と時刻」を指定します。
|
||||
# またその後ろにフォルダを指定することも出来ます
|
||||
# 例1> ./backup -r 200309191607
|
||||
# 例2> ./backup -r 200309191607 ../save ./backup_data/
|
||||
# この例では2003/09/19の16:07分にバックアップしたデータを復元しています
|
||||
#
|
||||
# 復元するとき、Athenaディレクトリにあるデータは *.bak に名前を変更して
|
||||
# 残しているので、いらない場合は rm *.bak などで消してください。
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
$sdir="../save/"; #バックアップ元(Athenaのディレクトリ/save/)
|
||||
$tdir="./backup_data/"; #バックアップ先
|
||||
|
||||
@files=( #ファイルのリスト
|
||||
"account","athena","storage","party","guild","castle","pet"
|
||||
);
|
||||
|
||||
|
||||
#-------------------------------設定ここまで-----------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if($ARGV[0]=~/^\-r$/i || $ARGV[0]=~/\-\-(recover|restore)/i){
|
||||
#復元処理
|
||||
|
||||
$file=$ARGV[1];
|
||||
$sdir=$ARGV[2]||$sdir;
|
||||
$tdir=$ARGV[3]||$tdir;
|
||||
&restorecopy($_) foreach @files;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#バックアップ処理
|
||||
$sdir=$ARGV[0]||$sdir;
|
||||
$tdir=$ARGV[1]||$tdir;
|
||||
|
||||
unless( -d $tdir ){
|
||||
print "$0: \"$tdir\" : No such directory\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(undef,$min,$hour,$day,$month,$year)=localtime;
|
||||
|
||||
$file=sprintf("%04d%02d%02d%02d%02d",
|
||||
$year+1900, $month+1, $day, $hour, $min );
|
||||
|
||||
&backupcopy($_) foreach @files;
|
||||
exit(0);
|
||||
|
||||
sub backupcopy {
|
||||
my($name)= @_;
|
||||
system("cp $sdir$name.txt $tdir$name$file.txt");
|
||||
}
|
||||
|
||||
sub restorecopy {
|
||||
my($name)= @_;
|
||||
unless( -f "$sdir$name.txt" ){
|
||||
printf("$0: \"$sdir$name.txt\" not found!\n");
|
||||
return 0;
|
||||
}
|
||||
unless( -f "$tdir$name$file.txt" ){
|
||||
printf("$0: \"$tdir$name$file.txt\" not found!\n");
|
||||
return 0;
|
||||
}
|
||||
rename "$sdir$name.txt","$sdir$name.bak";
|
||||
system("cp $tdir$name$file.txt $sdir$name.txt");
|
||||
}
|
204
src/tool/cgi/addaccount.cgi
Normal file
204
src/tool/cgi/addaccount.cgi
Normal file
@ -0,0 +1,204 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#=========================================================================
|
||||
# addaccount.cgi ver.1.00
|
||||
# ladminをラップした、アカウントを作成するCGI。
|
||||
# ladmin ver.1.04での動作を確認。
|
||||
#
|
||||
# ** 設定方法 **
|
||||
#
|
||||
# - 下の$ladmin変数にladminへのパスを設定すること。
|
||||
# - UNIX系OSで使用する場合はladminと共に改行コードを変換すること、また
|
||||
# ファイル先頭行をperlの正しいパスにすること。例> $ which perl
|
||||
# - サーバープログラムやブラウザによっては $cgiuri にこのファイルへの
|
||||
# 完全なURIをセットしなければならない場合もある。
|
||||
# - perlにパスが通っていない場合は $perl をperlへの正しいパスにすること。
|
||||
# - 他は普通のCGIと同じです。(実行権やcgi-binフォルダなど)
|
||||
#
|
||||
# ** その他 **
|
||||
# addaccount.cgi をブラウザで開くとサンプルHTML(そのまま使えます)が
|
||||
# 開きます。また、このcgiはブラウザから送られるAccept-Languageが
|
||||
# jaで始まっていればメッセージの一部を日本語に変換します。
|
||||
# (IEならインターネットオプションの言語設定で一番上に日本語を置く)
|
||||
# それ以外の場合は英語のまま出力します。
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
my($ladmin) = "../ladmin"; # ladminのパス(おそらく変更が必要)
|
||||
|
||||
my($cgiuri) = "./addaccount.cgi"; # このファイルのURI
|
||||
my($perl) = "perl"; # perlのコマンド名
|
||||
|
||||
|
||||
|
||||
#--------------------------- 設定ここまで --------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
use strict;
|
||||
use CGI;
|
||||
|
||||
my($cgi)= new CGI;
|
||||
my(%langconv)=(
|
||||
'Athena login-server administration tool.*' => '',
|
||||
'logged on.*' => '',
|
||||
);
|
||||
|
||||
# ----- 日本語環境なら変換テーブルをセット -----
|
||||
if($ENV{'HTTP_ACCEPT_LANGUAGE'}=~/^ja/){
|
||||
my(%tmp)=(
|
||||
'Account \[(.+)\] is successfully created.*'
|
||||
=> 'アカウント "$1" を作成しました.',
|
||||
'Account \[(.+)\] creation failed\. same account exists.*'
|
||||
=> 'アカウント "$1" は既に存在します.',
|
||||
'Illeagal charactor found in UserID.*'
|
||||
=> 'IDの中に不正な文字があります.',
|
||||
'Illeagal charactor found in Password.*'
|
||||
=> 'Passwordの中に不正な文字があります.',
|
||||
'input UserID 4-24 bytes.'
|
||||
=> 'IDは半角4~24文字で入力してください.',
|
||||
'input Password 4-24 bytes.'
|
||||
=> 'Passwordは半角4~24文字で入力してください.',
|
||||
'Illeagal gender.*'
|
||||
=> '性別がおかしいです.',
|
||||
'Cant connect to login server.*'
|
||||
=> 'ログインサーバーに接続できません.',
|
||||
'login error.*'
|
||||
=> 'ログインサーバーへの管理者権限ログインに失敗しました',
|
||||
"Can't execute ladmin.*"
|
||||
=> 'ladminの実行に失敗しました',
|
||||
'UserID "(.+)" is already used.*'
|
||||
=> 'ID "$1" は既に使用されています.',
|
||||
'You can use UserID \"(.+)\".*'
|
||||
=> 'ID "$1" は使用可能です.',
|
||||
|
||||
'account making' =>'アカウント作成',
|
||||
'\>UserID' =>'>ID',
|
||||
'\>Password' =>'>パスワード',
|
||||
'\>Gender' =>'>性別',
|
||||
'\>Male' =>'>男性',
|
||||
'\>Female' =>'>女性',
|
||||
'\"Make Account\"' =>'"アカウント作成"',
|
||||
'\"Check UserID\"' =>'"IDのチェック"',
|
||||
);
|
||||
map { $langconv{$_}=$tmp{$_}; } keys (%tmp);
|
||||
}
|
||||
|
||||
# ----- 追加 -----
|
||||
if( $cgi->param("addaccount") ){
|
||||
my($userid)= $cgi->param("userid");
|
||||
my($passwd)= $cgi->param("passwd");
|
||||
my($gender)= lc(substr($cgi->param("gender"),0,1));
|
||||
if(length($userid)<4 || length($userid)>24){
|
||||
HttpError("input UserID 4-24 bytes.");
|
||||
}
|
||||
if(length($passwd)<4 || length($passwd)>24){
|
||||
HttpError("input Password 4-24 bytes.");
|
||||
}
|
||||
if($userid=~/[^0-9A-Za-z\@\_\-\']/){
|
||||
HttpError("Illeagal charactor found in UserID.");
|
||||
}
|
||||
if($passwd=~/[\x00-\x1f\x80-\xff\']/){
|
||||
HttpError("Illeagal charactor found in Password.");
|
||||
}
|
||||
if($gender!~/[mf]/){
|
||||
HttpError("Gender error.");
|
||||
}
|
||||
open PIPE,"$perl $ladmin --add $userid $gender $passwd |"
|
||||
or HttpError("Can't execute ladmin.");
|
||||
my(@msg)=<PIPE>;
|
||||
close PIPE;
|
||||
HttpMsg(@msg);
|
||||
}
|
||||
# ----- 存在チェック -----
|
||||
elsif( $cgi->param("check") ){
|
||||
my($userid)= $cgi->param("userid");
|
||||
if(length($userid)<4 || length($userid)>24){
|
||||
HttpError("input UserID 4-24 bytes.");
|
||||
}
|
||||
if($userid=~/[^0-9A-Za-z\@\_\-\']/){
|
||||
HttpError("Illeagal charactor found in UserID.");
|
||||
}
|
||||
open PIPE,"$perl $ladmin --search --regex \\b$userid\\b |"
|
||||
or HttpError("Can't execute ladmin.");
|
||||
my(@msg)=<PIPE>;
|
||||
close PIPE;
|
||||
if(scalar(@msg)==6 && (split /[\s\0]+/,substr($msg[4],11,24))[0] eq $userid){
|
||||
HttpMsg("NG : UserID \"$userid\" is already used.");
|
||||
}elsif(scalar(@msg)==5){
|
||||
HttpMsg("OK : You can use UserID \"$userid\"");
|
||||
}
|
||||
HttpError("ladmin error ?\n---output---\n",@msg);
|
||||
}
|
||||
|
||||
# ----- フォーム -----
|
||||
else{
|
||||
print LangConv( <<"EOM" );
|
||||
Content-type: text/html\n
|
||||
<html>
|
||||
<head>
|
||||
<title>Athena account making cgi</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Athena account making cgi</h1>
|
||||
<form action="$cgiuri" method="post">
|
||||
<table border=2>
|
||||
<tr>
|
||||
<th>UserID</th>
|
||||
<td><input name="userid" size=24 maxlength=24></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Password</th>
|
||||
<td><input name="passwd" size=24 maxlength=24 type="password"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Gender</th>
|
||||
<td>
|
||||
<input type="radio" name="gender" value="male">Male
|
||||
<input type="radio" name="gender" value="female">Female
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
<input type="submit" name="addaccount" value="Make Account">
|
||||
<input type="submit" name="check" value="Check UserID">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
EOM
|
||||
exit;
|
||||
}
|
||||
|
||||
sub LangConv {
|
||||
my(@lst)= @_;
|
||||
my($a,$b,@out)=();
|
||||
foreach $a(@lst){
|
||||
foreach $b(keys %langconv){
|
||||
$a=~s/$b/$langconv{$b}/g;
|
||||
my($rep1)=$1;
|
||||
$a=~s/\$1/$rep1/g;
|
||||
}
|
||||
push @out,$a;
|
||||
}
|
||||
return @out;
|
||||
}
|
||||
|
||||
sub HttpMsg {
|
||||
my($msg)=join("", LangConv(@_));
|
||||
$msg=~s/\n/<br>\n/g;
|
||||
print LangConv("Content-type: text/html\n\n"),$msg;
|
||||
exit;
|
||||
}
|
||||
|
||||
sub HttpError {
|
||||
my($msg)=join("", LangConv(@_));
|
||||
$msg=~s/\n/<br>\n/g;
|
||||
print LangConv("Content-type: text/html\n\n"),$msg;
|
||||
exit;
|
||||
}
|
||||
|
85
src/tool/checkversion
Normal file
85
src/tool/checkversion
Normal file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
##########################################################################
|
||||
# INFORMATION TOOL ABOUT THE SERVERS VERSION OF ATHENA
|
||||
#
|
||||
# By connection on a server, this software display the version of the
|
||||
# designed server.
|
||||
#-------------------------------------------------------------------------
|
||||
# Usages:
|
||||
# ./checkversion IP:port
|
||||
# ./checkversion IP port
|
||||
# perl checkversion IP:port
|
||||
# perl checkversion IP port
|
||||
#
|
||||
# note: default port: 6900
|
||||
#
|
||||
# When successfull, the software return the value 0.
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
#------------------------- start of configuration ------------------------
|
||||
|
||||
$connecttimeout = 10; # Connection Timeout (in seconds)
|
||||
|
||||
#-------------------------- End of configuration -------------------------
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
unless($ARGV[0]) {
|
||||
print "USAGE: $0 server_ip:port\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$server = $ARGV[0];
|
||||
$port = $ARGV[1];
|
||||
$port = $1 if ($server =~ s/:(\d+)//);
|
||||
$port ||= 6900;
|
||||
|
||||
# Connection to the server
|
||||
my($so,$er) = ();
|
||||
eval{
|
||||
$so = IO::Socket::INET->new(
|
||||
PeerAddr=> $server,
|
||||
PeerPort=> $port,
|
||||
Proto => "tcp",
|
||||
Timeout => $connecttimeout) or $er = 1;
|
||||
};
|
||||
|
||||
if($er || $@) {
|
||||
print "Can't not connect to server [$server:$port] !\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
# Request for the server version
|
||||
print $so pack("v",30000); # 0x7530
|
||||
$so->flush();
|
||||
|
||||
# Receiving of the answer of the server
|
||||
if (read($so,$buf,10) < 10) {
|
||||
print "Invalid answer. It isn't an athena server or it is a too old version.\n";
|
||||
exit(5);
|
||||
}
|
||||
|
||||
# Sending end of connection to the server
|
||||
print $so pack("v",30002); # 0x7532
|
||||
$so->flush();
|
||||
|
||||
# Analyse of the answer
|
||||
my($ret,$maver,$miver,$rev,$dev,$mod,$type,$mdver) = unpack("v c6 v",$buf);
|
||||
|
||||
if ($ret != 30001) { # 0x7531
|
||||
print "Invalid answer. It isn't an athena server or it is a too old version.\n";
|
||||
exit(6);
|
||||
}
|
||||
|
||||
my(@stype) = ();
|
||||
foreach $i(0..3) {
|
||||
push @stype,(("login","char","inter","map")[$i]) if( $type & (1<<$i) );
|
||||
}
|
||||
print " ".join("/",@stype)." server [$server:$port].\n";
|
||||
printf " Athena version %s-%d.%d", ("stable","dev")[$dev], $maver,$miver;
|
||||
printf " revision %d",$rev if $rev;
|
||||
printf "%s%d\n",("","-mod")[$mod],$mdver;
|
||||
|
||||
exit(0);
|
296
src/tool/convert.c
Normal file
296
src/tool/convert.c
Normal file
@ -0,0 +1,296 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define RETCODE "\r\n"
|
||||
|
||||
#define MAX_INVENTORY 100
|
||||
#define MAX_CART 100
|
||||
#define MAX_SKILL 350
|
||||
#define GLOBAL_REG_NUM 16
|
||||
|
||||
struct item {
|
||||
int id;
|
||||
short nameid;
|
||||
short amount;
|
||||
short equip;
|
||||
char identify;
|
||||
char refine;
|
||||
char attribute;
|
||||
short card[4];
|
||||
};
|
||||
struct point{
|
||||
char map[16];
|
||||
short x,y;
|
||||
};
|
||||
struct skill {
|
||||
unsigned short id,lv,flag;
|
||||
};
|
||||
struct global_reg {
|
||||
char str[16];
|
||||
int value;
|
||||
};
|
||||
|
||||
struct mmo_charstatus {
|
||||
int char_id;
|
||||
int account_id;
|
||||
int base_exp,job_exp,zeny;
|
||||
|
||||
short class;
|
||||
short status_point,skill_point;
|
||||
short hp,max_hp,sp,max_sp;
|
||||
short option,karma,manner;
|
||||
short hair,hair_color,clothes_color;
|
||||
int party_id,guild_id,pet_id;
|
||||
|
||||
short weapon,shield;
|
||||
short head_top,head_mid,head_bottom;
|
||||
|
||||
char name[24];
|
||||
unsigned char base_level,job_level;
|
||||
unsigned char str,agi,vit,int_,dex,luk,char_num,sex;
|
||||
|
||||
struct point last_point,save_point,memo_point[3];
|
||||
struct item inventory[MAX_INVENTORY],cart[MAX_CART];
|
||||
struct skill skill[MAX_SKILL];
|
||||
int global_reg_num;
|
||||
struct global_reg global_reg[GLOBAL_REG_NUM];
|
||||
};
|
||||
|
||||
int mmo_char_tostr(char *str,struct mmo_charstatus *p)
|
||||
{
|
||||
int i;
|
||||
sprintf(str,"%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
|
||||
"\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
|
||||
"\t%s,%d,%d\t%s,%d,%d",
|
||||
p->char_id,p->account_id,p->char_num,p->name, //
|
||||
p->class,p->base_level,p->job_level,
|
||||
p->base_exp,p->job_exp,p->zeny,
|
||||
p->hp,p->max_hp,p->sp,p->max_sp,
|
||||
p->str,p->agi,p->vit,p->int_,p->dex,p->luk,
|
||||
p->status_point,p->skill_point,
|
||||
p->option,p->karma,p->manner, //
|
||||
p->party_id,p->guild_id,p->pet_id,
|
||||
p->hair,p->hair_color,p->clothes_color,
|
||||
p->weapon,p->shield,p->head_top,p->head_mid,p->head_bottom,
|
||||
p->last_point.map,p->last_point.x,p->last_point.y, //
|
||||
p->save_point.map,p->save_point.x,p->save_point.y
|
||||
);
|
||||
strcat(str,"\t");
|
||||
for(i=0;i<3;i++)
|
||||
if(p->memo_point[i].map[0]){
|
||||
sprintf(str+strlen(str),"%s,%d,%d",p->memo_point[i].map,p->memo_point[i].x,p->memo_point[i].y);
|
||||
}
|
||||
strcat(str,"\t");
|
||||
for(i=0;i<MAX_INVENTORY;i++)
|
||||
if(p->inventory[i].nameid){
|
||||
sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
|
||||
p->inventory[i].id,p->inventory[i].nameid,p->inventory[i].amount,p->inventory[i].equip,
|
||||
p->inventory[i].identify,p->inventory[i].refine,p->inventory[i].attribute,
|
||||
p->inventory[i].card[0],p->inventory[i].card[1],p->inventory[i].card[2],p->inventory[i].card[3]);
|
||||
}
|
||||
strcat(str,"\t");
|
||||
for(i=0;i<MAX_CART;i++)
|
||||
if(p->cart[i].nameid){
|
||||
sprintf(str+strlen(str),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
|
||||
p->cart[i].id,p->cart[i].nameid,p->cart[i].amount,p->cart[i].equip,
|
||||
p->cart[i].identify,p->cart[i].refine,p->cart[i].attribute,
|
||||
p->cart[i].card[0],p->cart[i].card[1],p->cart[i].card[2],p->cart[i].card[3]);
|
||||
}
|
||||
strcat(str,"\t");
|
||||
for(i=0;i<MAX_SKILL;i++)
|
||||
if(p->skill[i].id){
|
||||
sprintf(str+strlen(str),"%d,%d ",p->skill[i].id,p->skill[i].lv);
|
||||
}
|
||||
strcat(str,"\t");
|
||||
for(i=0;i<p->global_reg_num;i++)
|
||||
sprintf(str+strlen(str),"%s,%d ",p->global_reg[i].str,p->global_reg[i].value);
|
||||
strcat(str,"\t");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmo_char_fromstr(char *str,struct mmo_charstatus *p)
|
||||
{
|
||||
int tmp_int[256];
|
||||
int set,next,len,i;
|
||||
|
||||
set=sscanf(str,"%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d"
|
||||
"\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d"
|
||||
"\t%[^,],%d,%d\t%[^,],%d,%d%n",
|
||||
&tmp_int[0],&tmp_int[1],&tmp_int[2],p->name, //
|
||||
&tmp_int[3],&tmp_int[4],&tmp_int[5],
|
||||
&tmp_int[6],&tmp_int[7],&tmp_int[8],
|
||||
&tmp_int[9],&tmp_int[10],&tmp_int[11],&tmp_int[12],
|
||||
&tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],&tmp_int[18],
|
||||
&tmp_int[19],&tmp_int[20],
|
||||
&tmp_int[21],&tmp_int[22],&tmp_int[23], //
|
||||
&tmp_int[24],&tmp_int[25],
|
||||
&tmp_int[26],&tmp_int[27],&tmp_int[28],
|
||||
&tmp_int[29],&tmp_int[30],&tmp_int[31],&tmp_int[32],&tmp_int[33],
|
||||
p->last_point.map,&tmp_int[34],&tmp_int[35], //
|
||||
p->save_point.map,&tmp_int[36],&tmp_int[37],&next
|
||||
);
|
||||
p->char_id=tmp_int[0];
|
||||
p->account_id=tmp_int[1];
|
||||
p->char_num=tmp_int[2];
|
||||
p->class=tmp_int[3];
|
||||
p->base_level=tmp_int[4];
|
||||
p->job_level=tmp_int[5];
|
||||
p->base_exp=tmp_int[6];
|
||||
p->job_exp=tmp_int[7];
|
||||
p->zeny=tmp_int[8];
|
||||
p->hp=tmp_int[9];
|
||||
p->max_hp=tmp_int[10];
|
||||
p->sp=tmp_int[11];
|
||||
p->max_sp=tmp_int[12];
|
||||
p->str=tmp_int[13];
|
||||
p->agi=tmp_int[14];
|
||||
p->vit=tmp_int[15];
|
||||
p->int_=tmp_int[16];
|
||||
p->dex=tmp_int[17];
|
||||
p->luk=tmp_int[18];
|
||||
p->status_point=tmp_int[19];
|
||||
p->skill_point=tmp_int[20];
|
||||
p->option=tmp_int[21];
|
||||
p->karma=tmp_int[22];
|
||||
p->manner=tmp_int[23];
|
||||
p->party_id=tmp_int[24];
|
||||
p->guild_id=tmp_int[25];
|
||||
p->pet_id=0;
|
||||
p->hair=tmp_int[26];
|
||||
p->hair_color=tmp_int[27];
|
||||
p->clothes_color=tmp_int[28];
|
||||
p->weapon=tmp_int[29];
|
||||
p->shield=tmp_int[30];
|
||||
p->head_top=tmp_int[31];
|
||||
p->head_mid=tmp_int[32];
|
||||
p->head_bottom=tmp_int[33];
|
||||
p->last_point.x=tmp_int[34];
|
||||
p->last_point.y=tmp_int[35];
|
||||
p->save_point.x=tmp_int[36];
|
||||
p->save_point.y=tmp_int[37];
|
||||
if(set!=41)
|
||||
return 0;
|
||||
if(str[next]=='\n' || str[next]=='\r')
|
||||
return 1; // 新規データ
|
||||
next++;
|
||||
for(i=0;str[next] && str[next]!='\t';i++){
|
||||
set=sscanf(str+next,"%[^,],%d,%d%n",p->memo_point[i].map,&tmp_int[0],&tmp_int[1],&len);
|
||||
if(set!=3)
|
||||
return 0;
|
||||
p->memo_point[i].x=tmp_int[0];
|
||||
p->memo_point[i].y=tmp_int[1];
|
||||
next+=len;
|
||||
if(str[next]==' ')
|
||||
next++;
|
||||
}
|
||||
next++;
|
||||
for(i=0;str[next] && str[next]!='\t';i++){
|
||||
set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
|
||||
&tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3],
|
||||
&tmp_int[4],&tmp_int[5],&tmp_int[6],
|
||||
&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len);
|
||||
if(set!=11)
|
||||
return 0;
|
||||
p->inventory[i].id=tmp_int[0];
|
||||
p->inventory[i].nameid=tmp_int[1];
|
||||
p->inventory[i].amount=tmp_int[2];
|
||||
p->inventory[i].equip=tmp_int[3];
|
||||
p->inventory[i].identify=tmp_int[4];
|
||||
p->inventory[i].refine=tmp_int[5];
|
||||
p->inventory[i].attribute=tmp_int[6];
|
||||
p->inventory[i].card[0]=tmp_int[7];
|
||||
p->inventory[i].card[1]=tmp_int[8];
|
||||
p->inventory[i].card[2]=tmp_int[9];
|
||||
p->inventory[i].card[3]=tmp_int[10];
|
||||
next+=len;
|
||||
if(str[next]==' ')
|
||||
next++;
|
||||
}
|
||||
next++;
|
||||
for(i=0;str[next] && str[next]!='\t';i++){
|
||||
set=sscanf(str+next,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
|
||||
&tmp_int[0],&tmp_int[1],&tmp_int[2],&tmp_int[3],
|
||||
&tmp_int[4],&tmp_int[5],&tmp_int[6],
|
||||
&tmp_int[7],&tmp_int[8],&tmp_int[9],&tmp_int[10],&len);
|
||||
if(set!=11)
|
||||
return 0;
|
||||
p->cart[i].id=tmp_int[0];
|
||||
p->cart[i].nameid=tmp_int[1];
|
||||
p->cart[i].amount=tmp_int[2];
|
||||
p->cart[i].equip=tmp_int[3];
|
||||
p->cart[i].identify=tmp_int[4];
|
||||
p->cart[i].refine=tmp_int[5];
|
||||
p->cart[i].attribute=tmp_int[6];
|
||||
p->cart[i].card[0]=tmp_int[7];
|
||||
p->cart[i].card[1]=tmp_int[8];
|
||||
p->cart[i].card[2]=tmp_int[9];
|
||||
p->cart[i].card[3]=tmp_int[10];
|
||||
next+=len;
|
||||
if(str[next]==' ')
|
||||
next++;
|
||||
}
|
||||
next++;
|
||||
for(i=0;str[next] && str[next]!='\t';i++){
|
||||
set=sscanf(str+next,"%d,%d%n",
|
||||
&tmp_int[0],&tmp_int[1],&len);
|
||||
if(set!=2)
|
||||
return 0;
|
||||
p->skill[tmp_int[0]].id=tmp_int[0];
|
||||
p->skill[tmp_int[0]].lv=tmp_int[1];
|
||||
next+=len;
|
||||
if(str[next]==' ')
|
||||
next++;
|
||||
}
|
||||
next++;
|
||||
for(i=0;str[next] && str[next]!='\t' && str[next]!='\n' && str[next]!='\r';i++){ //global_reg実装以前のathena.txt互換のため一応'\n'チェック
|
||||
set=sscanf(str+next,"%[^,],%d%n",
|
||||
p->global_reg[i].str,&p->global_reg[i].value,&len);
|
||||
if(set!=2)
|
||||
return 0;
|
||||
next+=len;
|
||||
if(str[next]==' ')
|
||||
next++;
|
||||
}
|
||||
p->global_reg_num=i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mmo_char_convert(char *fname1,char *fname2)
|
||||
{
|
||||
char line[65536];
|
||||
int ret;
|
||||
struct mmo_charstatus char_dat;
|
||||
FILE *ifp,*ofp;
|
||||
|
||||
ifp=fopen(fname1,"r");
|
||||
ofp=fopen(fname2,"w");
|
||||
if(ifp==NULL) {
|
||||
printf("file not found %s\n",fname1);
|
||||
return 0;
|
||||
}
|
||||
if(ofp==NULL) {
|
||||
printf("file open error %s\n",fname2);
|
||||
return 0;
|
||||
}
|
||||
while(fgets(line,65535,ifp)){
|
||||
memset(&char_dat,0,sizeof(struct mmo_charstatus));
|
||||
ret=mmo_char_fromstr(line,&char_dat);
|
||||
if(ret){
|
||||
mmo_char_tostr(line,&char_dat);
|
||||
fprintf(ofp,"%s" RETCODE,line);
|
||||
}
|
||||
}
|
||||
fcloseall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
if(argc < 3) {
|
||||
printf("Usage: convert <input filename> <output filename>\n");
|
||||
exit(0);
|
||||
}
|
||||
mmo_char_convert(argv[1],argv[2]);
|
||||
|
||||
return 0;
|
||||
}
|
122
src/tool/getlogincount
Normal file
122
src/tool/getlogincount
Normal file
@ -0,0 +1,122 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
##########################################################################
|
||||
# INFORMATION TOOL ABOUT THE # OF ONLINE PLAYERS ON ATHENA SERVERS
|
||||
#
|
||||
# By connection on the athena login-server, this software displays the
|
||||
# number of online players.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
# Software usage:
|
||||
# Configure the IP, the port and a valid account of the server.
|
||||
# After, use at your choice:
|
||||
# ./getlogincount - display the number of online players on all servers.
|
||||
# ./getlogincount --premier or
|
||||
# ./getlogincount --first -- display the number of online players of the
|
||||
# first server in the received list.
|
||||
# ./getlogincount [servername] -- display the number of online players
|
||||
# of the specified server.
|
||||
#
|
||||
# If successfull, the software return the value 0.
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
#------------------------------ CONFIGURATION ----------------------------
|
||||
|
||||
$loginserverip = "127.0.0.1"; # IP of the login-server
|
||||
$loginserverport = 6900; # port of the login-server
|
||||
$loginaccount = "s1"; # a valid account name
|
||||
$loginpasswd = "p1"; # the password of the valid account name
|
||||
|
||||
$connecttimeout = 10; # Connection timeout (in seconds)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
my($sname) = $ARGV[0];
|
||||
if (!defined($sname)) {
|
||||
$sname = "";
|
||||
}
|
||||
|
||||
# Connection to the login-server
|
||||
my($so,$er) = ();
|
||||
eval{
|
||||
$so = IO::Socket::INET->new(
|
||||
PeerAddr=> $loginserverip,
|
||||
PeerPort=> $loginserverport,
|
||||
Proto => "tcp",
|
||||
Timeout => $connecttimeout) or $er=1;
|
||||
};
|
||||
if($er || $@){
|
||||
print "Can't not connect to the login-server [${loginserverip}:$loginserverport] !\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
# Request to connect on login-server
|
||||
print $so pack("v V a24 a24 C",0x0064,9,$loginaccount,$loginpasswd,3);
|
||||
$so->flush();
|
||||
|
||||
# Fail to connect
|
||||
if(unpack("v", &soread(\$so,2)) != 0x0069) {
|
||||
print "Login error.\n";
|
||||
exit(3);
|
||||
}
|
||||
|
||||
# Get length of the received packet
|
||||
my($plen) = unpack("v",&soread(\$so,2))-4;
|
||||
|
||||
# Suppress information of the account (we need only information about the servers)
|
||||
&soread(\$so,43);
|
||||
$plen -= 43;
|
||||
|
||||
# Check about the number of online servers
|
||||
if ($plen < 32) {
|
||||
printf "No server is connected to login-server.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
# Read information of the servers
|
||||
my(@slist) = ();
|
||||
for(;$plen > 0;$plen -= 32) {
|
||||
my($name,$count) = unpack("x6 a20 V",&soread(\$so,32));
|
||||
$name = substr($name,0,index($name,"\0"));
|
||||
push @slist, [ $name, $count ];
|
||||
}
|
||||
|
||||
# Display the result
|
||||
if($sname eq "--first" || $sname eq "--premier") { # If we ask only for the first server
|
||||
printf "%-20s : %5d\n",$slist[0][0],$slist[0][1];
|
||||
} elsif ($sname eq "") { # If we ask for all servers
|
||||
foreach $i(@slist) {
|
||||
printf "%-20s : %5d\n",$i->[0],$i->[1];
|
||||
}
|
||||
} else { # If we ask for a specified server (by its name)
|
||||
my($flag) = 1;
|
||||
foreach $i(@slist) {
|
||||
if($i->[0] eq $sname) {
|
||||
printf "%-20s : %5d\n",$i->[0],$i->[1];
|
||||
$flag = 0;
|
||||
}
|
||||
}
|
||||
if($flag) { # If the server doesn't exist
|
||||
printf "The server [$sname] doesn't exist.\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
# End of the software
|
||||
$so->shutdown(2);
|
||||
$so->close();
|
||||
exit(0);
|
||||
|
||||
# Sub-function: get data from the socket
|
||||
sub soread {
|
||||
my($so,$len) = @_;
|
||||
my($sobuf);
|
||||
if(read($$so,$sobuf,$len) < $len) {
|
||||
print "Socket read error.\n";
|
||||
exit(5);
|
||||
}
|
||||
return $sobuf;
|
||||
};
|
3793
src/tool/ladmin
Normal file
3793
src/tool/ladmin
Normal file
File diff suppressed because it is too large
Load Diff
34
src/tool/mapcheck.sh
Normal file
34
src/tool/mapcheck.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
echo "============================================"
|
||||
echo "= map server status checker... ="
|
||||
echo "============================================"
|
||||
./map-server.exe &
|
||||
sleep 40
|
||||
|
||||
while [ 0 ]
|
||||
do
|
||||
pcpu=` top -n 1| grep map-server | awk '{print $9}' | awk 'BEGIN{FS="."} {print $1}' `
|
||||
if [ "$pcpu" -gt 80 ];then
|
||||
echo "============================================"
|
||||
echo "map server is more than 80% (now $pcpu%)"
|
||||
echo "============================================"
|
||||
ppid=` ps -a | grep map-server | awk '{print $1}' `
|
||||
kill $ppid
|
||||
./map-server.exe &
|
||||
sleep 40
|
||||
else
|
||||
pmapct=` ps -a| grep map-server | wc -l `
|
||||
if [ "$pmapct" -eq 0 ];then
|
||||
echo "============================================"
|
||||
echo "map server is not running..."
|
||||
echo "restart map server..."
|
||||
echo "============================================"
|
||||
./map-server.exe &
|
||||
sleep 40
|
||||
#echo "test"
|
||||
else
|
||||
echo "map server is ok (now $pcpu%)..."
|
||||
sleep 5
|
||||
fi
|
||||
fi
|
||||
done
|
56
src/tool/mapchecker.sh
Normal file
56
src/tool/mapchecker.sh
Normal file
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
athena_dir="/home/athena/658/"
|
||||
|
||||
while [ true ] ; do
|
||||
|
||||
if [ ` ps fauxw | grep map-server | grep -v grep | wc -l ` -eq 0 ];then
|
||||
#echo `date` " -- map-server crashed - restarting"
|
||||
echo `date` " -- map-server crashed - restarting" >> /var/log/athena_status.log
|
||||
killall -9 map-server
|
||||
cd $athena_dir
|
||||
nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
|
||||
sleep 240
|
||||
#sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
|
||||
fi
|
||||
|
||||
|
||||
if [ ` ps fauxw | grep map-server | grep -v grep | awk '{print $3}' | awk 'BEGIN{FS="."} {print $1}' ` -gt 10 ];then
|
||||
#echo `date` " -- mapserver cpuload over 10 - restarting"
|
||||
echo `date` " -- mapserver cpuload over 10 - restarting" >> /var/log/athena_status.log
|
||||
killall -9 map-server
|
||||
cd $athena_dir
|
||||
nohup ./map-server ./conf/map_athena.conf ./inter_athena.conf &
|
||||
sleep 240
|
||||
#sleep 40 #for fast pc's remove the "#" at the beginning of the line and delete the line above
|
||||
#echo `date` " -- restarted"
|
||||
echo `date` " -- restarted" >> /var/log/athena_status.log
|
||||
fi
|
||||
|
||||
if [ ` ps fauxw | grep char-server | grep -v grep | wc -l ` -eq 0 ];then
|
||||
#echo `date` " -- char server crashed - restarting"
|
||||
echo `date` " -- char server crashed - restarting" >> /var/log/athena_status.log
|
||||
killall -9 char-server
|
||||
cd $athena_dir
|
||||
nohup ./char-server ./conf/char_athena.conf ./conf/inter_athena.conf &
|
||||
#echo `date` " -- restarted"
|
||||
echo `date` " -- restarted" >> /var/log/athena_status.log
|
||||
|
||||
fi
|
||||
|
||||
if [ ` ps fauxw | grep login-server | grep -v grep | wc -l ` -eq 0 ];then
|
||||
#echo `date` " -- login server crashed - restarting"
|
||||
echo `date` " -- login server crashed - restarting" >> /var/log/athena_status.log
|
||||
killall -9 login-server
|
||||
cd $athena_dir
|
||||
nohup ./login-server ./conf/login_athena.conf &
|
||||
#echo `date` " -- restarted"
|
||||
echo `date` " -- restarted" >> /var/log/athena_status.log
|
||||
|
||||
fi
|
||||
|
||||
|
||||
#echo `date` " -- everything is fine"
|
||||
echo `date` " -- everything is fine" >> /var/log/athena_status.log
|
||||
sleep 30
|
||||
done
|
20
src/webserver/Makefile
Normal file
20
src/webserver/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
all:
|
||||
#Generate framework...
|
||||
$(CC) -c parse.c
|
||||
$(CC) -c generate.c
|
||||
$(CC) -c htmlstyle.c
|
||||
$(CC) -c logs.c
|
||||
|
||||
#Generate "pages"...
|
||||
cd pages && $(CC) -c about.c && cd ..
|
||||
cd pages && $(CC) -c sample.c && cd ..
|
||||
cd pages && $(CC) -c notdone.c && cd ..
|
||||
|
||||
#Building the server...
|
||||
$(CC) -o webserver main.c parse.o generate.o htmlstyle.o \
|
||||
logs.o pages/about.o pages/sample.o pages/notdone.o
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f pages/*.o
|
||||
rm -f webserver
|
50
src/webserver/doc/API.txt
Normal file
50
src/webserver/doc/API.txt
Normal file
@ -0,0 +1,50 @@
|
||||
Here's the webserver API, so you can work on the webserver.
|
||||
|
||||
My personal goal is to make this interface simple, so that coding it
|
||||
will be like coding in some scripting language...
|
||||
|
||||
|
||||
|
||||
char *get_param(char in_string[500], char swhat[500]);
|
||||
|
||||
This function simply returns various data from the query string.
|
||||
*Pass get_param NOTHING longer than 500 in length!
|
||||
|
||||
What do I pass where in_string is?
|
||||
The query string.
|
||||
|
||||
What do I pass where swhat is?
|
||||
One of two things...
|
||||
Either 0 for the path of the 'page'
|
||||
or you can pass it the param you wish to lookup.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char *get_query(char *inquery);
|
||||
|
||||
This function simply returns a query string from the raw server request.
|
||||
This is used once in main, I doubt you'll need it.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void web_send(int sockin, char *in_data);
|
||||
|
||||
Super easy way of sending data to a webpage!
|
||||
Simply put in the socket name and then the data.
|
||||
|
||||
Ex:
|
||||
web_send(socket, "I like cheese!\n");
|
||||
|
||||
|
||||
|
||||
|
||||
char *html_header(char* title);
|
||||
Easy way to print the eAthena header for the server.
|
||||
|
||||
Ex:
|
||||
web_send(sockethere, html_header("About"));
|
11
src/webserver/doc/README
Normal file
11
src/webserver/doc/README
Normal file
@ -0,0 +1,11 @@
|
||||
This readme is intended for the programmers of eAthena.
|
||||
|
||||
This webserver's apis are in API.txt.
|
||||
|
||||
To make this simple, generate.c should handle most of the work this sever does
|
||||
in terms of what people see.
|
||||
|
||||
When a request is made the server shoots it off to generate.c.
|
||||
|
||||
You are welcome to create more functions used by generate.c to generate pages
|
||||
though, so don't feel limited by that one file.
|
38
src/webserver/generate.c
Normal file
38
src/webserver/generate.c
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
void generate_page(char password[25], int sock_in, char *query, char *ip)
|
||||
{
|
||||
char *page = get_param(query, 0);
|
||||
char *ppass = get_param(query, "password");
|
||||
|
||||
|
||||
if ( (ppass == 0) || (strcmp(password, ppass) != 0) )
|
||||
{
|
||||
web_send(sock_in, html_header("Enter your password"));
|
||||
web_send(sock_in, "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n");
|
||||
web_send(sock_in, "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n");
|
||||
web_send(sock_in, "<input type=\"submit\" value=\"Login\">\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
//To make this simple, we will have a bunch of if statements
|
||||
//that then shoot out data off into functions.
|
||||
|
||||
|
||||
//The 'index'
|
||||
if ( strcmp(page, "/") == 0 )
|
||||
generate_notdone(sock_in, query, ip);
|
||||
|
||||
|
||||
//About page:
|
||||
if ( strcmp(page, "/about.html") == 0 )
|
||||
generate_about(sock_in, query, ip);
|
||||
|
||||
|
||||
//Test page:
|
||||
if ( strcmp(page, "/testing/") == 0 )
|
||||
generate_sample(sock_in, query, ip);
|
||||
|
||||
}
|
||||
}
|
51
src/webserver/htmlstyle.c
Normal file
51
src/webserver/htmlstyle.c
Normal file
@ -0,0 +1,51 @@
|
||||
char output[10000];
|
||||
|
||||
char *html_header(char *title)
|
||||
{
|
||||
memset(output, 0x0, 10000);
|
||||
char *text = "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n"
|
||||
"<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n"
|
||||
"align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n"
|
||||
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n"
|
||||
"<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n"
|
||||
"<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n"
|
||||
"<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n"
|
||||
"</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n"
|
||||
"cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n";
|
||||
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n"
|
||||
"cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>"
|
||||
"<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">"
|
||||
"<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n"
|
||||
"To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n"
|
||||
"</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n"
|
||||
"<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n"
|
||||
"<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n"
|
||||
"cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n"
|
||||
"<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n"
|
||||
"<b>Athena</b> « Portal »</font></td></tr></tbody></table></td></tr></tbody>"
|
||||
"</table></td></tr></tbody></table>\n";
|
||||
|
||||
sprintf(output, "<title>%s</title>\n%s\n", title, text);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *html_start_form(char *location, char *action)
|
||||
{
|
||||
memset(output, 0x0, 10000);
|
||||
sprintf(output, "<form action=\"%s\" method=\"%s\">", location, action);
|
||||
return output;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *html_end_forum(void)
|
||||
{
|
||||
return "</form>";
|
||||
}
|
||||
|
||||
|
||||
|
8
src/webserver/logs.c
Normal file
8
src/webserver/logs.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <time.h>
|
||||
|
||||
void log_visit(char *query, char *ip)
|
||||
{
|
||||
time_t timer;
|
||||
timer=time(NULL);
|
||||
printf("%s - \"%s\" - %s", ip, query, asctime(localtime(&timer)));
|
||||
}
|
142
src/webserver/main.c
Normal file
142
src/webserver/main.c
Normal file
@ -0,0 +1,142 @@
|
||||
/***************************************************************************
|
||||
description
|
||||
-------------------
|
||||
author : (C) 2004 by Michael J. Flickinger
|
||||
email : mjflick@cpan.org
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define BLOG 10
|
||||
|
||||
char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
|
||||
char recvin[500], password[25];
|
||||
int s_port;
|
||||
|
||||
void sigchld_handler(int s)
|
||||
{
|
||||
while(wait(NULL) > 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
printf("eAthena Web Server\n");
|
||||
printf("usage: %s [password] [port]\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
s_port = atoi(argv[2]);
|
||||
|
||||
if ((s_port < 1) || (s_port > 65534))
|
||||
{
|
||||
printf("Error: The port you choose is not valid port.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) > 25)
|
||||
{
|
||||
printf("Error: Your password is too long.\n");
|
||||
printf("It must be shorter than 25 characters.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
memset(password, 0x0, 25);
|
||||
memcpy(password, argv[1], strlen(argv[1]));
|
||||
|
||||
int sockfd, new_fd;
|
||||
struct sockaddr_in my_addr;
|
||||
struct sockaddr_in their_addr;
|
||||
int sin_size;
|
||||
|
||||
struct sigaction sa;
|
||||
|
||||
int yes=1;
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1)
|
||||
{
|
||||
perror("Darn, this is broken.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
|
||||
{
|
||||
perror("Error... :-(");
|
||||
}
|
||||
|
||||
//Now we know we have a working socket. :-)
|
||||
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(s_port);
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(my_addr.sin_zero), '\0', 8);
|
||||
|
||||
if ( bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
|
||||
{
|
||||
perror("can not bind to this port");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ( listen(sockfd, BLOG) == -1)
|
||||
{
|
||||
perror("can not listen on port");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sa.sa_handler = sigchld_handler;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART;
|
||||
|
||||
if (sigaction(SIGCHLD, &sa, NULL) == -1)
|
||||
{
|
||||
perror("sigaction sucks");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("The eAthena webserver is up and listening on port %i.\n", s_port);
|
||||
|
||||
while(1)
|
||||
{
|
||||
sin_size = sizeof(struct sockaddr_in);
|
||||
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
|
||||
|
||||
if (!fork())
|
||||
{
|
||||
close(sockfd);
|
||||
memset(recvin, 0x0, 500);
|
||||
recv(new_fd, recvin, 500, 0);
|
||||
send(new_fd, header, strlen(header), 0);
|
||||
generate_page(password, new_fd, get_query(recvin), inet_ntoa(their_addr.sin_addr));
|
||||
log_visit(get_query(recvin), inet_ntoa(their_addr.sin_addr));
|
||||
|
||||
close(new_fd);
|
||||
exit(0);
|
||||
}
|
||||
close(new_fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
6
src/webserver/pages/about.c
Normal file
6
src/webserver/pages/about.c
Normal file
@ -0,0 +1,6 @@
|
||||
void generate_about(int sock_in, char *query, char *ip)
|
||||
{
|
||||
//printf("%s", html_header("About"));
|
||||
web_send(sock_in, html_header("About"));
|
||||
web_send(sock_in, "<center>eAthena Web Server!</center>\n");
|
||||
}
|
5
src/webserver/pages/notdone.c
Normal file
5
src/webserver/pages/notdone.c
Normal file
@ -0,0 +1,5 @@
|
||||
void generate_notdone(int sock_in, char *query, char *ip)
|
||||
{
|
||||
web_send(sock_in, "<title>Not here!</title>\n");
|
||||
web_send(sock_in, "<h2><center>This page/feature is not done yet.</center>\n</h2>");
|
||||
}
|
24
src/webserver/pages/sample.c
Normal file
24
src/webserver/pages/sample.c
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
void generate_sample(int sock_in, char *query, char *ip)
|
||||
{
|
||||
|
||||
char *name = get_param(query, "name");
|
||||
|
||||
web_send(sock_in, "<title>SAMPLE</title>\n");
|
||||
|
||||
|
||||
//If a name was not entered...
|
||||
if ( name == '\0' )
|
||||
{
|
||||
web_send(sock_in, "<form action=\"/testing/\" method=\"GET\">\n");
|
||||
web_send(sock_in, "<input type=\"text\" name=\"name\">\n");
|
||||
web_send(sock_in, "<input type=\"submit\">\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
web_send(sock_in, "Your name is: ");
|
||||
web_send(sock_in, get_param(query, "name"));
|
||||
}
|
||||
printf("OK!\n");
|
||||
}
|
135
src/webserver/parse.c
Normal file
135
src/webserver/parse.c
Normal file
@ -0,0 +1,135 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
char filtered_query[2000];
|
||||
char rdata[500];
|
||||
char param_n[500];
|
||||
char param_d[500];
|
||||
|
||||
|
||||
char *get_query(char *inquery)
|
||||
{
|
||||
memset(filtered_query, 0x0, 2000);
|
||||
sscanf(inquery, "GET %s %[$]", filtered_query);
|
||||
return(filtered_query);
|
||||
}
|
||||
|
||||
void web_send(int sockin, char *in_data)
|
||||
{
|
||||
send(sockin, in_data, strlen(in_data), 0);
|
||||
}
|
||||
|
||||
|
||||
//THIS IS BAD CODE BE CAREFULL WITH IT!
|
||||
//Watch out for buffer overflow...
|
||||
//When using please make sure to check the string size.
|
||||
|
||||
//Also note:
|
||||
//I take no pride in this code, it is a really bad way of doing this...
|
||||
char *get_param(char in_string[500], char swhat[500])
|
||||
{
|
||||
int i = 0;
|
||||
int marker, iswitch, pint, dint;
|
||||
char flux[500];
|
||||
memset(flux, 0x0, 500);
|
||||
|
||||
//Get the path of out "page"
|
||||
if (swhat == 0)
|
||||
{
|
||||
//while i is not equal to array size
|
||||
while (i != 500)
|
||||
{
|
||||
//if there is a question mark, halt!
|
||||
if (in_string[i] == '?')
|
||||
{
|
||||
i = 499;
|
||||
}
|
||||
else
|
||||
rdata[i] = in_string[i];
|
||||
|
||||
i++;
|
||||
}
|
||||
return rdata;
|
||||
}
|
||||
else //so, we want a param...
|
||||
{
|
||||
//calculate where param begins
|
||||
while (i != 500)
|
||||
{
|
||||
if (in_string[i] == '?')
|
||||
{
|
||||
marker = i + 1;
|
||||
i = 499;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
//keep morons from trying to crash this
|
||||
if ((marker > 500)||(marker < 1))
|
||||
marker = 500;
|
||||
|
||||
while(marker != 500)
|
||||
{
|
||||
if ((in_string[marker] != '&') && (in_string[marker] != '\0'))
|
||||
{
|
||||
flux[i] = in_string[marker];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//we have a param, now we must dig through it
|
||||
|
||||
//clear temp vars
|
||||
memset(param_n, 0x0, 500);
|
||||
memset(param_d, 0x0, 500);
|
||||
iswitch = 0;
|
||||
pint = 0;
|
||||
dint = 0;
|
||||
i = 0;
|
||||
|
||||
//split result into param_n and param_d
|
||||
while(i != 500)
|
||||
{
|
||||
if ( (flux[i] != '=') && (flux[i] != '\0') )
|
||||
{
|
||||
if (iswitch == 0)
|
||||
{
|
||||
param_n[pint] = flux[i];
|
||||
pint++;
|
||||
}
|
||||
else
|
||||
{
|
||||
param_d[dint] = flux[i];
|
||||
dint++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iswitch = 1;
|
||||
}
|
||||
if (flux[i] == '\0')
|
||||
i = 499;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( strcmp(param_n, swhat) == 0 )
|
||||
{
|
||||
return param_d;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (in_string[marker] == '\0')
|
||||
{
|
||||
marker = 499;
|
||||
}
|
||||
marker++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user