From: Jeremy Stanley Date: Sun, 18 Sep 2005 23:42:03 +0000 (+0000) Subject: Imported from archive. X-Git-Tag: 0.0.1~332 X-Git-Url: https://mudpy.org/gitweb?p=mudpy.git;a=commitdiff_plain;h=98c1ce3a29f1cb35df7da79c95ac9fcb8a4a8e1f Imported from archive. * mudpy.py (User.negotiate_telnet_options): Added support for RFC 1184 linemode and RFC 858 go ahead suppression. Automated end of record/go ahead prompt terminator selection via Telnet option negotiation. Added support for Telnet suboption negotiation. Fixed a double-IAC escape matching error. (User.send): Refactored away some spaghetti logic for better readability. (log): Added syslog support. --- diff --git a/example b/example index a086a5f..e98f25d 100644 --- a/example +++ b/example @@ -1,38 +1,39 @@ -[location:101] -pickproof_n = yes -name = East Sixth Avenue -closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North. -terrain = city -link_e = location:102 -keywords_n = ['booth'] -description_n = This is a simple merchant's booth. -link_w = location:161 -link_n = location:159 - -[location:106] -keywords_e = ['shop'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East. +[location:127] +keywords_e = ['booth'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East. closeable_e = yes pickproof_e = yes terrain = city -link_e = location:152 -name = North Fifth Street -description_e = This is the entrance to a shop. -link_s = location:105 -link_n = location:107 +link_e = location:143 +link_n = location:128 +description_e = This is a simple merchant's booth. +link_s = location:126 +name = South First Street -[location:118] -pickproof_n = yes -name = East Fourth Avenue -closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North. +[location:120] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Fourth Avenue while Fifth Street leads North. terrain = city -link_e = location:119 -keywords_n = ['booth'] -description_n = This is a simple merchant's booth. -link_w = location:116 -link_n = location:147 +name = The Corner of Fifth and Fourth +link_w = location:119 +link_n = location:121 + +[location:143] +link_w = location:127 +terrain = inside +name = New BuildWalk Room +description = This unfinished room was created by Imp. + +[location:132] +keywords_e = ['booth'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East. +closeable_e = yes +pickproof_e = yes +terrain = city +link_e = location:141 +link_n = location:133 +description_e = This is a simple merchant's booth. +link_s = location:131 +name = North First Street [location:159] link_s = location:101 @@ -49,16 +50,17 @@ link_s = location:129 pickproof_s = yes description = Shoes, shoes and more shoes... You need footwear, we have footwear. Look around, see what you like. Best prices in town! So you gonna buy something, stranger? -[location:104] -keywords_e = ['gate'] -name = East Market Gate +[location:122] +keywords_e = ['shop'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East. closeable_e = yes pickproof_e = yes terrain = city -link_e = location:0 -description_e = This gate leads from the market to the city proper. -link_w = location:103 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the East. +link_e = location:150 +link_n = location:103 +description_e = This is the entrance to a shop. +link_s = location:121 +name = South Fifth Street [location:151] terrain = inside @@ -67,26 +69,26 @@ link_e = location:105 description = This unfinished room was created by Imp. [location:150] -terrain = inside link_w = location:122 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:153] -link_n = location:108 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:108 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:152] -terrain = inside link_w = location:106 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:155] -terrain = inside link_w = location:114 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. @@ -97,10 +99,10 @@ name = New BuildWalk Room description = This unfinished room was created by Imp. [location:157] -link_n = location:130 terrain = inside -description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface. +link_n = location:130 name = Tailor's Booth +description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface. [location:156] terrain = inside @@ -110,15 +112,15 @@ description = This unfinished room was created by Imp. [location:115] link_n = location:114 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = South Seventh Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:116 pickproof_w = yes link_w = location:156 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West. +name = South Seventh Street [location:114] keywords_e = ['booth'] @@ -127,62 +129,62 @@ closeable_e = yes pickproof_e = yes terrain = city link_e = location:155 -name = South Seventh Street +link_n = location:161 description_e = This is a simple merchant's booth. link_s = location:115 -link_n = location:161 +name = South Seventh Street [location:117] description_s = This gate leads from the market to the city proper. +link_n = location:116 description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the North, Seventh Street heads into the market while the rest of the city lies trough the gate to the South. terrain = city -name = South Market Gate closeable_s = yes keywords_s = ['gate'] link_s = location:0 pickproof_s = yes -link_n = location:116 +name = South Market Gate [location:116] link_n = location:115 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Fourth Avenue while Seventh Street runs North and South. terrain = city link_e = location:118 -name = South Seventh and Fourth link_s = location:117 link_w = location:123 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Fourth Avenue while Seventh Street runs North and South. +name = South Seventh and Fourth [location:111] pickproof_n = yes name = North Market Gate closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Seventh Street heads into the market while the rest of the city lies trough the gate to the North. terrain = city +link_n = location:0 keywords_n = ['gate'] link_s = location:110 description_n = This gate leads from the market to the city proper. -link_n = location:0 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Seventh Street heads into the market while the rest of the city lies trough the gate to the North. [location:110] link_n = location:111 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Third Avenue while Seventh Street runs North and South. terrain = city link_e = location:109 -name = North Seventh and Third link_s = location:112 link_w = location:135 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Third Avenue while Seventh Street runs North and South. +name = North Seventh and Third [location:113] link_n = location:112 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = North Seventh Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:161 pickproof_w = yes link_w = location:137 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Seventh Street runs North and South here while a merchant's booth lies to the West. +name = North Seventh Street [location:112] keywords_e = ['booth'] @@ -191,10 +193,10 @@ closeable_e = yes pickproof_e = yes terrain = city link_e = location:138 -name = North Seventh Street +link_n = location:110 description_e = This is a simple merchant's booth. link_s = location:113 -link_n = location:110 +name = North Seventh Street [location:137] terrain = inside @@ -204,14 +206,14 @@ description = This unfinished room was created by Imp. [location:136] description_w = This gate leads from the market to the city proper. +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the West. terrain = city link_e = location:128 -name = West Market Gate keywords_w = ['gate'] closeable_w = yes pickproof_w = yes link_w = location:0 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the West. +name = West Market Gate [location:135] description_s = This is a simple merchant's booth. @@ -229,13 +231,13 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = West Third Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North. terrain = city link_e = location:135 +link_n = location:140 keywords_n = ['shop'] description_n = This is the entrance to a shop. link_w = location:133 -link_n = location:140 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North. [location:119] description_s = This is the entrance to a shop. @@ -249,29 +251,29 @@ link_w = location:118 pickproof_s = yes description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South. -[location:132] -keywords_e = ['booth'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East. -closeable_e = yes -pickproof_e = yes +[location:118] +pickproof_n = yes +name = East Fourth Avenue +closeable_n = yes terrain = city -link_e = location:141 -name = North First Street -description_e = This is a simple merchant's booth. -link_s = location:131 -link_n = location:133 +link_e = location:119 +link_n = location:147 +keywords_n = ['booth'] +description_n = This is a simple merchant's booth. +link_w = location:116 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North. [location:131] link_n = location:132 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West. terrain = city -name = North First Street keywords_w = ['shop'] closeable_w = yes description_w = This is the entrance to a shop. link_s = location:128 pickproof_w = yes link_w = location:142 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West. +name = North First Street [location:130] description_s = This is a simple merchant's booth. @@ -285,29 +287,23 @@ link_w = location:129 pickproof_s = yes description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the South. -[location:105] -link_n = location:106 +[location:123] +description_s = This is the entrance to a shop. +name = West Fourth Avenue terrain = city -name = North Fifth Street -keywords_w = ['booth'] -closeable_w = yes -description_w = This is a simple merchant's booth. -link_s = location:103 -pickproof_w = yes -link_w = location:151 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West. - -[location:138] -terrain = inside -link_w = location:112 -name = New BuildWalk Room -description = This unfinished room was created by Imp. +link_e = location:116 +closeable_s = yes +keywords_s = ['shop'] +link_s = location:146 +link_w = location:124 +pickproof_s = yes +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South. [location:148] -link_n = location:119 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:119 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:149] terrain = inside @@ -316,10 +312,10 @@ link_e = location:121 description = This unfinished room was created by Imp. [location:146] -link_n = location:123 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:123 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:147] link_s = location:118 @@ -345,9 +341,9 @@ name = New BuildWalk Room link_e = location:131 description = This unfinished room was created by Imp. -[location:143] +[location:138] +link_w = location:112 terrain = inside -link_w = location:127 name = New BuildWalk Room description = This unfinished room was created by Imp. @@ -358,26 +354,26 @@ name = New BuildWalk Room description = This unfinished room was created by Imp. [location:141] -terrain = inside link_w = location:132 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:160] -link_n = location:102 terrain = inside -description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you. +link_n = location:102 name = Blacksmith's Booth +description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you. [location:161] link_n = location:113 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Seventh Street runs North and South. A short flight of stairs leads up to the bandstand. terrain = city link_e = location:101 -name = Second Square link_s = location:114 link_w = location:130 link_u = location:100 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Seventh Street runs North and South. A short flight of stairs leads up to the bandstand. +name = Second Square [location:108] description_s = This is a simple merchant's booth. @@ -395,28 +391,28 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = East Third Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North. terrain = city link_e = location:108 +link_n = location:154 keywords_n = ['shop'] description_n = This is the entrance to a shop. link_w = location:110 -link_n = location:154 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Third Avenue runs East and West here while a storefront beckons to the North. [location:128] link_n = location:131 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while First Street runs North and South. terrain = city link_e = location:129 -name = First and West Sixth link_s = location:127 link_w = location:136 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while First Street runs North and South. +name = First and West Sixth [location:139] -link_n = location:135 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:135 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:102] description_s = This is a simple merchant's booth. @@ -432,85 +428,89 @@ description = You find the hustle and bustle of this place remarkably distractin [location:103] link_n = location:105 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Fifth Street runs North and South. terrain = city link_e = location:104 -name = Fifth and East Sixth link_s = location:122 link_w = location:102 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sixth Avenue while Fifth Street runs North and South. +name = Fifth and East Sixth [location:100] +link_d = location:161 terrain = inside description = The stand is currently not in use for a performance, but shoppers gather here to rest and chat with one another. A pleasantly cool breeze coupled with a nice view of the market make this a good place to relax and recover energy. name = The Bandstand -link_d = location:161 -[location:127] -keywords_e = ['booth'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a merchant's booth lies to the East. -closeable_e = yes -pickproof_e = yes +[location:101] +pickproof_n = yes +name = East Sixth Avenue +closeable_n = yes terrain = city -link_e = location:143 -name = South First Street -description_e = This is a simple merchant's booth. -link_s = location:126 -link_n = location:128 +link_e = location:102 +link_n = location:159 +keywords_n = ['booth'] +description_n = This is a simple merchant's booth. +link_w = location:161 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North. -[location:120] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Fourth Avenue while Fifth Street leads North. +[location:106] +keywords_e = ['shop'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East. +closeable_e = yes +pickproof_e = yes terrain = city -name = The Corner of Fifth and Fourth -link_w = location:119 -link_n = location:121 +link_e = location:152 +link_n = location:107 +description_e = This is the entrance to a shop. +link_s = location:105 +name = North Fifth Street [location:121] link_n = location:122 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = South Fifth Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:120 pickproof_w = yes link_w = location:149 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West. +name = South Fifth Street -[location:122] -keywords_e = ['shop'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a storefront beckons to the East. +[location:104] +keywords_e = ['gate'] +name = East Market Gate closeable_e = yes pickproof_e = yes terrain = city -link_e = location:150 -name = South Fifth Street -description_e = This is the entrance to a shop. -link_s = location:121 -link_n = location:103 +link_e = location:0 +description_e = This gate leads from the market to the city proper. +link_w = location:103 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Sixth Avenue heads into the market while the rest of the city lies trough the gate to the East. -[location:123] -description_s = This is the entrance to a shop. -name = West Fourth Avenue +[location:105] +link_n = location:106 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fifth Street runs North and South here while a merchant's booth lies to the West. terrain = city -link_e = location:116 -closeable_s = yes -keywords_s = ['shop'] -link_s = location:146 -link_w = location:124 -pickproof_s = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a storefront beckons to the South. +keywords_w = ['booth'] +closeable_w = yes +description_w = This is a simple merchant's booth. +link_s = location:103 +pickproof_w = yes +link_w = location:151 +name = North Fifth Street [location:124] pickproof_n = yes name = West Fourth Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North. terrain = city link_e = location:123 +link_n = location:145 keywords_n = ['booth'] description_n = This is a simple merchant's booth. link_w = location:125 -link_n = location:145 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Fourth Avenue runs East and West here while a merchant's booth lies to the North. [location:133] name = The Corner of First and Third @@ -523,20 +523,20 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = West Sixth Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North. terrain = city link_e = location:130 +link_n = location:158 keywords_n = ['booth'] description_n = This is a simple merchant's booth. link_w = location:128 -link_n = location:158 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sixth Avenue runs East and West here while a merchant's booth lies to the North. [location:125] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Fourth Avenue while First Street leads North. +link_n = location:126 terrain = city link_e = location:124 name = The Corner of First and Fourth -link_n = location:126 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Fourth Avenue while First Street leads North. [location:107] name = The Corner of Fifth and Third @@ -547,13 +547,13 @@ description = You find the hustle and bustle of this place remarkably distractin [location:126] link_n = location:127 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West. terrain = city -name = South First Street keywords_w = ['shop'] closeable_w = yes description_w = This is the entrance to a shop. link_s = location:125 pickproof_w = yes link_w = location:144 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. First Street runs North and South here while a storefront beckons to the West. +name = South First Street diff --git a/menu b/menu index c96399b..a9f6f0e 100644 --- a/menu +++ b/menu @@ -95,6 +95,8 @@ error_weak = That is a weak password... Try something at least 7 characters long prompt = Enter a new password for "$(account)": error_differs = The two passwords did not match. Try again... +[menu:initial] + [menu:main_utility] action_c = user.new_avatar() branch_a = activate_avatar diff --git a/mudpy.py b/mudpy.py index 6326e77..61330b9 100644 --- a/mudpy.py +++ b/mudpy.py @@ -11,7 +11,8 @@ from os.path import abspath, dirname, exists, isabs, join as path_join from random import choice, randrange from socket import AF_INET, SO_REUSEADDR, SOCK_STREAM, SOL_SOCKET, socket from stat import S_IMODE, ST_MODE -from telnetlib import DO, DONT, ECHO, EOR, IAC, WILL, WONT +from syslog import LOG_PID, LOG_INFO, LOG_DAEMON, closelog, openlog, syslog +from telnetlib import DO, DONT, ECHO, EOR, GA, IAC, LINEMODE, SB, SE, SGA, WILL, WONT from time import asctime, sleep class Element: @@ -199,13 +200,15 @@ class User: self.connection = None self.authenticated = False self.password_tries = 0 - self.state = "entering_account_name" + self.state = "initial" self.menu_seen = False self.error = "" self.input_queue = [] self.output_queue = [] self.partial_input = "" self.echoing = True + self.terminator = IAC+GA + self.negotiation_pause = 0 self.avatar = None self.account = None @@ -299,7 +302,7 @@ class User: """Send the user their current menu.""" if not self.menu_seen: self.menu_choices = get_menu_choices(self) - self.send(get_menu(self.state, self.error, self.echoing, self.menu_choices), "") + self.send(get_menu(self.state, self.error, self.echoing, self.terminator, self.menu_choices), "") self.menu_seen = True self.error = False self.adjust_echoing() @@ -313,31 +316,34 @@ class User: """Remove a user from the list of connected users.""" universe.userlist.remove(self) - def send(self, output, eol="$(eol)"): + def send(self, output, eol="$(eol)", raw=False): """Send arbitrary text to a connected user.""" - # start with a newline, append the message, then end - # with the optional eol string passed to this function - # and the ansi escape to return to normal text - output = "\r\n" + output + eol + chr(27) + "[0m" + # unless raw mode is on, clean it up all nice and pretty + if not raw: - # find and replace macros in the output - output = replace_macros(self, output) + # we'll take out GA or EOR and add them back on the end + if output.endswith(IAC+GA) or output.endswith(IAC+EOR): + terminate = True + output = output[:-2] + else: terminate = False - # wrap the text at 80 characters - output = wrap_ansi_text(output, 80) + # start with a newline, append the message, then end + # with the optional eol string passed to this function + # and the ansi escape to return to normal text + output = "\r\n" + output + eol + chr(27) + "[0m" - # drop the formatted output into the output queue - self.output_queue.append(output) + # find and replace macros in the output + output = replace_macros(self, output) - # try to send the last item in the queue and remove it - try: - self.connection.send(self.output_queue[0]) - del self.output_queue[0] + # wrap the text at 80 characters + output = wrap_ansi_text(output, 80) - # but if we can't, that's okay too - except: - pass + # tack the terminator back on + if terminate: output += self.terminator + + # drop the output into the user's output queue + self.output_queue.append(output) def pulse(self): """All the things to do to the user per increment.""" @@ -347,8 +353,13 @@ class User: self.state = "disconnecting" self.menu_seen = False + # if output is paused, decrement the counter + if self.state == "initial": + if self.negotiation_pause: self.negotiation_pause -= 1 + else: self.state = "entering_account_name" + # show the user a menu as needed - self.show_menu() + else: self.show_menu() # disconnect users with the appropriate state if self.state == "disconnecting": self.quit() @@ -356,6 +367,16 @@ class User: # the user is unique and not flagged to disconnect else: + # try to send the last item in the queue and remove it + if self.output_queue: + try: + self.connection.send(self.output_queue[0]) + del self.output_queue[0] + + # but if we can't, that's okay too + except: + pass + # check for input and add it to the queue self.enqueue_input() @@ -436,25 +457,51 @@ class User: # if there wasn't an IAC in the input, skip to the end if position < 0: position = len(text) - # replace a double (literal) IAC and move on + # replace a double (literal) IAC if there's an LF later elif len(text) > position+1 and text[position+1] == IAC: - text = text.replace(IAC+IAC, IAC) + if text.find("\n", position) > 0: text = text.replace(IAC+IAC, IAC) + else: position += 1 position += 1 # this must be an option negotiation elif len(text) > position+2 and text[position+1] in (DO, DONT, WILL, WONT): + negotiation = text[position+1:position+3] + # if we turned echo off, ignore the confirmation - if not self.echoing and text[position+1:position+3] == DO+ECHO: pass + if not self.echoing and negotiation == DO+ECHO: pass + + # allow LINEMODE + elif negotiation == WILL+LINEMODE: self.send(IAC+DO+LINEMODE, raw=True) + + # if the client likes EOR instead of GA, make a note of it + elif negotiation == DO+EOR: self.terminator = IAC+EOR + elif negotiation == DONT+EOR and self.terminator == IAC+EOR: + self.terminator = IAC+GA + + # if the client doesn't want GA, oblige + elif negotiation == DO+SGA and self.terminator == IAC+GA: + self.terminator = "" + self.send(IAC+WILL+SGA, raw=True) # we don't want to allow anything else - elif text[position+1] in (DO, WILL): self.send(IAC+WONT+text[position+2]) + elif text[position+1] == DO: self.send(IAC+WONT+text[position+2], raw=True) + elif text[position+1] == WILL: self.send(IAC+DONT+text[position+2], raw=True) # strip the negotiation from the input text = text.replace(text[position:position+3], "") + # get rid of IAC SB .* IAC SE + elif len(text) > position+4 and text[position:position+2] == IAC+SB: + end_subnegotiation = text.find(IAC+SE, position) + if end_subnegotiation > 0: text = text[:position] + text[end_subnegotiation+2:] + else: position += 1 + # otherwise, strip out a two-byte IAC command - else: text = text.replace(text[position:position+2], "") + elif len(text) > position+2: text = text.replace(text[position:position+2], "") + + # and this means we got the begining of an IAC + else: position += 1 # replace the input with our cleaned-up text self.partial_input = text @@ -527,6 +574,11 @@ def log(message): # send the timestamp and message to standard output print(timestamp + " " + message) + # send the message to the system log + openlog("mudpy", LOG_PID, LOG_INFO | LOG_DAEMON) + syslog(message) + closelog() + def wrap_ansi_text(text, width): """Wrap text with arbitrary width while ignoring ANSI colors.""" @@ -757,12 +809,19 @@ def check_for_connection(listening_socket): # set the user's ipa from the connection's ipa user.address = address[0] + # let the client know we WILL EOR + user.send(IAC+WILL+EOR, raw=True) + user.negotiation_pause = 2 + # return the new user object return user -def get_menu(state, error=None, echoing=True, choices={}): +def get_menu(state, error=None, echoing=True, terminator="", choices=None): """Show the correct menu text to a user.""" + # make sure we don't reuse a mutable sequence by default + if choices is None: choices = {} + # begin with a telnet echo command sequence if needed message = get_echo_sequence(state, echoing) @@ -781,8 +840,8 @@ def get_menu(state, error=None, echoing=True, choices={}): # display a message indicating if echo is off message += get_echo_message(state) - # tack on IAC EOR to indicate the prompt will not be followed by CRLF - message += IAC+EOR + # tack on EOR or GA to indicate the prompt will not be followed by CRLF + message += terminator # return the assembly of various strings defined above return message