diff --git a/OpenRA.FileFormats/Support/Log.cs b/OpenRA.FileFormats/Support/Log.cs index 3749bec046..df242a81dc 100755 --- a/OpenRA.FileFormats/Support/Log.cs +++ b/OpenRA.FileFormats/Support/Log.cs @@ -20,28 +20,76 @@ using System.IO; using System; +using System.Collections.Generic; +using System.Linq; +using System.IO.Compression; +using System.Net; namespace OpenRA { + public struct ChannelInfo + { + public bool Upload; + public string Filename; + public StreamWriter Writer; + public bool Diff; + } + public static class Log { - public static string Filename = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar + "openra.log.txt"; - - static StreamWriter writer = File.CreateText(Filename); + public static string LogPathPrefix = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar; + static Dictionary channels = new Dictionary(); static Log() { + AddChannel("debug", "openra.log.txt", false, false); + } + + public static void AddChannel(string channelName, string filename, bool upload, bool diff) + { + StreamWriter writer = File.CreateText(LogPathPrefix + filename); writer.AutoFlush = true; + + channels.Add(channelName, new ChannelInfo() { Upload = upload, Filename = filename, Writer = writer, Diff = diff }); } - public static void Write(string format, params object[] args) + public static void Write(string channel, string format, params object[] args) { - writer.WriteLine(format, args); + ChannelInfo info; + if (!channels.TryGetValue(channel, out info)) + throw new Exception("Tried logging to non-existant channel " + channel); + + info.Writer.WriteLine(format, args); } - public static void Close() + public static void Upload(int gameId) { - writer.Close(); + foreach (var kvp in channels.Where(x => x.Value.Upload)) + { + kvp.Value.Writer.Close(); + var logfile = File.OpenRead(Log.LogPathPrefix + kvp.Value.Filename); + byte[] fileContents = logfile.ReadAllBytes(); + var ms = new MemoryStream(); + + using (var gzip = new GZipStream(ms, CompressionMode.Compress, true)) + gzip.Write(fileContents, 0, fileContents.Length); + + ms.Position = 0; + byte[] buffer = ms.ReadAllBytes(); + + WebRequest request = WebRequest.Create("http://open-ra.org/logs/upload.php"); + request.ContentType = "application/x-gzip"; + request.ContentLength = buffer.Length; + request.Method = "POST"; + request.Headers.Add("Game-ID", gameId.ToString()); + request.Headers.Add("Channel", kvp.Key); + request.Headers.Add("Diff", kvp.Value.Diff ? "1" : "0"); + + using (var requestStream = request.GetRequestStream()) + requestStream.Write(buffer, 0, buffer.Length); + + var response = (HttpWebResponse)request.GetResponse(); + } } } } diff --git a/OpenRA.FileFormats/Support/Timer.cs b/OpenRA.FileFormats/Support/Timer.cs index d9b3e4d17d..6c4a146ae2 100755 --- a/OpenRA.FileFormats/Support/Timer.cs +++ b/OpenRA.FileFormats/Support/Timer.cs @@ -30,7 +30,7 @@ namespace OpenRA.Support var time = sw.ElapsedTime(); var dt = time - lastTime; if( dt > 0.0001 ) - Log.Write( message, dt ); + Log.Write("debug", message, dt ); lastTime = time; } } diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index 5ae4ce36ea..c0204270f5 100755 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -201,7 +201,7 @@ namespace OpenRA if (Health > maxHP) Health = maxHP; -// Log.Write("InflictDamage: {0} #{1} -> {2} #{3} raw={4} adj={5} hp={6} mod={7}", +// Log.Write("debug", "InflictDamage: {0} #{1} -> {2} #{3} raw={4} adj={5} hp={6} mod={7}", // attacker.Info.Name, attacker.ActorID, Info.Name, ActorID, rawDamage, damage, Health, modifier); var newState = GetDamageState(); diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index 4326f05f2b..24f6d270e6 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -104,7 +104,7 @@ namespace OpenRA a( x ); var dt = sw.ElapsedTime() - t; if( dt > time ) - Log.Write( text, x, dt*1000 ); + Log.Write("debug", text, x, dt * 1000); } ); } } diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 253200c5ed..057a2749d1 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -68,7 +68,7 @@ namespace OpenRA static internal bool scrollDown = false; static internal bool scrollLeft = false; static internal bool scrollRight = false; - + static void LoadModPackages(Manifest manifest) { FileSystem.UnmountAll(); @@ -175,13 +175,12 @@ namespace OpenRA internal static string CurrentHost = ""; internal static int CurrentPort = 0; - internal static void JoinServer(int id, string host, int port) + internal static void JoinServer(string host, int port) { if (orderManager != null) orderManager.Dispose(); CurrentHost = host; CurrentPort = port; - MasterGameID = id; orderManager = new OrderManager(new NetworkConnection(host, port), ChooseReplayFilename()); } @@ -255,12 +254,12 @@ namespace OpenRA var f = syncReports.FirstOrDefault(a => a.First == frame); if (f == null) { - Log.Write("No sync report available!"); + Log.Write("sync", "No sync report available!"); return; } - Log.Write("Sync for net frame {0} -------------", f.First); - Log.Write("{0}", f.Second); + Log.Write("sync", "Sync for net frame {0} -------------", f.First); + Log.Write("sync", "{0}", f.Second); } static void Tick() @@ -601,6 +600,8 @@ namespace OpenRA LoadShellMap(new Manifest(LobbyInfo.GlobalSettings.Mods).ShellmapUid); ResetTimer(); + + Log.AddChannel("sync", "openra.syncreport.txt", true, true); } static void LoadUserSettings(Settings settings) @@ -638,5 +639,26 @@ namespace OpenRA Chrome.rootWidget.CloseWindow(); Chrome.rootWidget.OpenWindow("MAINMENU_BG"); } + + internal static int GetGameId() + { + try + { + string s = File.ReadAllText(Log.LogPathPrefix + "openra.gameid"); + return int.Parse(s); + } + catch (Exception) + { + return 0; + } + } + + internal static void SetGameId(int id) + { + var file = File.CreateText(Log.LogPathPrefix + "openra.gameid"); + file.Write(id); + file.Flush(); + file.Close(); + } } } diff --git a/OpenRA.Game/GameRules/Rules.cs b/OpenRA.Game/GameRules/Rules.cs index 3c09691860..3f036380d1 100755 --- a/OpenRA.Game/GameRules/Rules.cs +++ b/OpenRA.Game/GameRules/Rules.cs @@ -38,11 +38,11 @@ namespace OpenRA public static void LoadRules(Manifest m, Map map) { - Log.Write("Using rules files: "); + Log.Write("debug", "Using rules files: "); foreach (var y in m.Rules) - Log.Write(" -- {0}", y); + Log.Write("debug", " -- {0}", y); - Log.Write("Using Map: {0}",map.Uid); + Log.Write("debug", "Using Map: {0}",map.Uid); Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y)); Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value)); diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 6b1606a8d3..fa35084110 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -564,7 +564,10 @@ namespace OpenRA.Server static void PingMasterServerResponse(object sender, DownloadDataCompletedEventArgs e) { string s = Encoding.UTF8.GetString(e.Result); - int.TryParse(s.Trim(), out Game.MasterGameID); + int gameId; + if (int.TryParse(s.Trim(), out gameId)) + Game.SetGameId(gameId); + Log.Write("debug", "Game ID: {0}", gameId); } } } diff --git a/OpenRA.Game/Sound.cs b/OpenRA.Game/Sound.cs index fdcb0043ae..1f4013150b 100644 --- a/OpenRA.Game/Sound.cs +++ b/OpenRA.Game/Sound.cs @@ -214,7 +214,7 @@ namespace OpenRA Al.alGenSources(1, out source); if (0 != Al.alGetError()) { - Log.Write("Failed generating OpenAL source {0}", i); + Log.Write("debug", "Failed generating OpenAL source {0}", i); return; } diff --git a/OpenRA.Game/Support/Program.cs b/OpenRA.Game/Support/Program.cs index 5bfee93d30..8292b6a263 100644 --- a/OpenRA.Game/Support/Program.cs +++ b/OpenRA.Game/Support/Program.cs @@ -36,9 +36,9 @@ namespace OpenRA // brutal hack Application.CurrentCulture = CultureInfo.InvariantCulture; - if( Debugger.IsAttached ) + if (Debugger.IsAttached) { - Run( args ); + Run(args); return; } @@ -48,38 +48,13 @@ namespace OpenRA } catch( Exception e ) { - Log.Write( "{0}", e.ToString() ); - UploadLog(); + Log.AddChannel("exception", "openra.exception.txt", true, false); + Log.Write("exception", "{0}", e.ToString()); + Log.Upload(Game.GetGameId()); throw; } } - static void UploadLog() - { - Log.Close(); - var logfile = File.OpenRead(Log.Filename); - byte[] fileContents = logfile.ReadAllBytes(); - var ms = new MemoryStream(); - - using (var gzip = new GZipStream(ms, CompressionMode.Compress, true)) - gzip.Write(fileContents, 0, fileContents.Length); - - ms.Position = 0; - byte[] buffer = ms.ReadAllBytes(); - - WebRequest request = WebRequest.Create("http://open-ra.org/logs/upload.php"); - request.ContentType = "application/x-gzip"; - request.ContentLength = buffer.Length; - request.Method = "POST"; - request.Headers.Add("Game-ID", Game.MasterGameID.ToString()); - - using (var requestStream = request.GetRequestStream()) - requestStream.Write(buffer, 0, buffer.Length); - - var response = (HttpWebResponse)request.GetResponse(); - MessageBox.Show("{0} {1}:{2}".F(Game.MasterGameID, Game.CurrentHost, Game.CurrentPort)); - } - static void Run( string[] args ) { Game.Initialize( new Settings( args ) ); diff --git a/OpenRA.Game/Traits/World/BibLayer.cs b/OpenRA.Game/Traits/World/BibLayer.cs index 8781b38512..1b5594c85e 100644 --- a/OpenRA.Game/Traits/World/BibLayer.cs +++ b/OpenRA.Game/Traits/World/BibLayer.cs @@ -68,8 +68,8 @@ namespace OpenRA.Traits int bib = Array.IndexOf(info.BibWidths,size); if (bib < 0) - { - Log.Write("Cannot bib {0}-wide building {1}",size,b.Info.Name); + { + Log.Write("debug", "Cannot bib {0}-wide building {1}", size, b.Info.Name); return; } diff --git a/OpenRA.Game/Widgets/Delegates/ConnectionDialogsDelegate.cs b/OpenRA.Game/Widgets/Delegates/ConnectionDialogsDelegate.cs index 5821cf19d0..6af772931c 100644 --- a/OpenRA.Game/Widgets/Delegates/ConnectionDialogsDelegate.cs +++ b/OpenRA.Game/Widgets/Delegates/ConnectionDialogsDelegate.cs @@ -36,7 +36,7 @@ namespace OpenRA.Widgets.Delegates return true; }; r.GetWidget("CONNECTION_BUTTON_RETRY").OnMouseUp = mi => { - Game.JoinServer(Game.MasterGameID, Game.CurrentHost, Game.CurrentPort); + Game.JoinServer(Game.CurrentHost, Game.CurrentPort); return true; }; diff --git a/OpenRA.Game/Widgets/Delegates/CreateServerMenuDelegate.cs b/OpenRA.Game/Widgets/Delegates/CreateServerMenuDelegate.cs index de6192212a..68146c7b35 100644 --- a/OpenRA.Game/Widgets/Delegates/CreateServerMenuDelegate.cs +++ b/OpenRA.Game/Widgets/Delegates/CreateServerMenuDelegate.cs @@ -42,7 +42,7 @@ namespace OpenRA.Widgets.Delegates r.GetWidget("CREATESERVER_BUTTON_START").OnMouseUp = mi => { r.OpenWindow("SERVER_LOBBY"); - Log.Write("Creating server"); + Log.Write("debug", "Creating server"); // TODO: Get this from a map chooser string map = Game.AvailableMaps.Keys.FirstOrDefault(); @@ -57,8 +57,8 @@ namespace OpenRA.Widgets.Delegates gameName, Game.Settings.ListenPort, Game.Settings.ExternalPort, mods, map); - Log.Write("Joining server"); - Game.JoinServer(0, IPAddress.Loopback.ToString(), Game.Settings.ListenPort); + Log.Write("debug", "Joining server"); + Game.JoinServer(IPAddress.Loopback.ToString(), Game.Settings.ListenPort); return true; }; diff --git a/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs b/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs index 38b1576271..19b16bc9e7 100644 --- a/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs +++ b/OpenRA.Game/Widgets/Delegates/ServerBrowserDelegate.cs @@ -76,7 +76,8 @@ namespace OpenRA.Widgets.Delegates OnMouseUp = nmi => { r.GetWidget("JOINSERVER_BG").Visible = false; - Game.JoinServer(g.Id, g.Address.Split(':')[0], int.Parse(g.Address.Split(':')[1])); + Game.JoinServer(g.Address.Split(':')[0], int.Parse(g.Address.Split(':')[1])); + Game.SetGameId(g.Id); return true; }, }; @@ -128,7 +129,7 @@ namespace OpenRA.Widgets.Delegates r.GetWidget("JOINSERVER_BUTTON_DIRECTCONNECT").OnMouseUp = mi => { /* rude hack. kill this as soon as we can do a direct connect via the commandline */ r.CloseWindow(); - Game.JoinServer(0, Game.Settings.NetworkHost, Game.Settings.NetworkPort); + Game.JoinServer(Game.Settings.NetworkHost, Game.Settings.NetworkPort); return true; }; } diff --git a/OpenRA.Gl/GraphicsDevice.cs b/OpenRA.Gl/GraphicsDevice.cs index 713d07e683..5343c7dc67 100644 --- a/OpenRA.Gl/GraphicsDevice.cs +++ b/OpenRA.Gl/GraphicsDevice.cs @@ -213,8 +213,6 @@ namespace OpenRA.GlRenderer Game.HandleKeyPress(new KeyPressEventArgs(keyName[0]), mods); else if (keyName == "f4" && ((mods & Modifiers.Alt) != 0)) OpenRA.Game.Exit(); - else if (keyName == "f5") - throw new Exception("F5 Pressed."); } } break; diff --git a/OpenRA.Mods.RA/BridgeLayer.cs b/OpenRA.Mods.RA/BridgeLayer.cs index 9b4927ccb1..3a6823329f 100644 --- a/OpenRA.Mods.RA/BridgeLayer.cs +++ b/OpenRA.Mods.RA/BridgeLayer.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.RA void ConvertBridgeToActor(World w, int i, int j) { - Log.Write("Converting bridge at {0} {1}",i,j); + Log.Write("debug", "Converting bridge at {0} {1}", i, j); var tile = w.Map.MapTiles[i, j].type; var image = w.Map.MapTiles[i, j].image; diff --git a/web/logs/upload.php b/web/logs/upload.php index 8e956265ec..5ce07d6bca 100644 --- a/web/logs/upload.php +++ b/web/logs/upload.php @@ -1,19 +1,159 @@ + + Copyright (C) 2005 Nils Knappmeier next version + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://www.gnu.org/licenses/gpl.html + + About: + I searched a function to compare arrays and the array_diff() + was not specific enough. It ignores the order of the array-values. + So I reimplemented the diff-function which is found on unix-systems + but this you can use directly in your code and adopt for your needs. + Simply adopt the formatline-function. with the third-parameter of arr_diff() + you can hide matching lines. Hope someone has use for this. + + Contact: d.u.diff@holomind.de + **/ + + +## PHPDiff returns the differences between $old and $new, formatted +## in the standard diff(1) output format. +function PHPDiff($old,$new) +{ + # split the source text into arrays of lines + $t1 = explode("\n",$old); + $x=array_pop($t1); + if ($x>'') $t1[]="$x\n\\ No newline at end of file"; + $t2 = explode("\n",$new); + $x=array_pop($t2); + if ($x>'') $t2[]="$x\n\\ No newline at end of file"; + + # build a reverse-index array using the line as key and line number as value + # don't store blank lines, so they won't be targets of the shortest distance + # search + foreach($t1 as $i=>$x) if ($x>'') $r1[$x][]=$i; + foreach($t2 as $i=>$x) if ($x>'') $r2[$x][]=$i; + + $a1=0; $a2=0; # start at beginning of each list + $actions=array(); + + # walk this loop until we reach the end of one of the lists + while ($a1=$s1) { $d=$n; break; } + if ($d>=$s1 && ($d+$s2-$a1-$a2)<($best1+$best2-$a1-$a2)) + { $best1=$d; $best2=$s2; } + $d=-1; + foreach((array)@$r2[$t1[$s1]] as $n) + if ($n>=$s2) { $d=$n; break; } + if ($d>=$s2 && ($s1+$d-$a1-$a2)<($best1+$best2-$a1-$a2)) + { $best1=$s1; $best2=$d; } + $s1++; $s2++; + } + while ($a1<$best1) { $actions[]=1; $a1++; } # deleted elements + while ($a2<$best2) { $actions[]=2; $a2++; } # added elements + } + + # we've reached the end of one list, now walk to the end of the other + while($a10) { + $xstr = ($x1==($x0+1)) ? $x1 : ($x0+1).",$x1"; + $ystr = ($y1==($y0+1)) ? $y1 : ($y0+1).",$y1"; + if ($op==1) $out[] = "{$xstr}d{$y1}"; + elseif ($op==3) $out[] = "{$xstr}c{$ystr}"; + while ($x0<$x1) { $out[] = '< '.$t1[$x0]; $x0++; } # deleted elems + if ($op==2) $out[] = "{$x1}a{$ystr}"; + elseif ($op==3) $out[] = '---'; + while ($y0<$y1) { $out[] = '> '.$t2[$y0]; $y0++; } # added elems + } + $x1++; $x0=$x1; + $y1++; $y0=$y1; + $op=0; + } + $out[] = ''; + return join("\n",$out); +} + + +?> + +$entry) { + if ($entry!='.' && $entry!='..' && fnmatch($mask, $entry) ) { + $sdir[] = $entry; + } + } + return ($sdir); +} +?> + open($game_id.'.zip', ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); +mkdir($game_id); + +$client_hash = md5($_SERVER['REMOTE_ADDR']); $post_data = ''; while (!feof($post_file)) $post_data .= fread($post_file, 8192); +if ($_SERVER['HTTP_DIFF']) { + foreach (sdir($game_id, '*.'.$_SERVER['HTTP_CHANNEL'].'.log') as $f) { + $hash = substr($f, 0, strpos($f, '.')); + $diff = PHPDiff(file_get_contents($game_id . '/' . $f), $post_data); + file_put_contents($game_id .'/'. $hash .'.'. $client_hash .'.'. $_SERVER['HTTP_CHANNEL'] . '.diff', $diff); + } +} -$log_zip->addFromString(md5($_SERVER['REMOTE_ADDR']).'.log',$post_data); +file_put_contents($game_id .'/'. $client_hash . '.' . $_SERVER['HTTP_CHANNEL'] . '.log',$post_data); fclose($post_file); -$log_zip->close(); ?>