Support [...] ranges.  Also [!...] for negated ranges, SYSV shell style.
diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py
index c7caef6..1e7dbb3 100644
--- a/Lib/fnmatch.py
+++ b/Lib/fnmatch.py
@@ -1,28 +1,64 @@
 # module 'fnmatch' -- filename matching with shell patterns
 
-# XXX [] patterns are not supported (but recognized)
-
 def fnmatch(name, pat):
-	if '*' in pat or '?' in pat or '[' in pat:
-		return fnmatch1(name, pat)
-	return name = pat
+	#
+	# Check for simple case: no special characters
+	#
+	if not ('*' in pat or '?' in pat or '[' in pat):
+		return name = pat
+	#
+	# Check for common cases: *suffix and prefix*
+	#
+	if pat[0] = '*':
+		p1 = pat[1:]
+		if not ('*' in p1 or '?' in p1 or '[' in p1):
+			start = len(name) - len(p1)
+			return start >= 0 and name[start:] = p1
+	elif pat[-1:] = '*':
+		p1 = pat[:-1]
+		if not ('*' in p1 or '?' in p1 or '[' in p1):
+			return name[:len(p1)] = p1
+	#
+	# General case
+	#
+	return fnmatch1(name, pat)
 
 def fnmatch1(name, pat):
 	for i in range(len(pat)):
 		c = pat[i]
 		if c = '*':
-			restpat = pat[i+1:]
-			if '*' in restpat or '?' in restpat or '[' in restpat:
-				for i in range(i, len(name)):
-					if fnmatch1(name[i:], restpat):
-						return 1
-				return 0
-			else:
-				return name[len(name)-len(restpat):] = restpat
+			p1 = pat[i+1:]
+			if not ('*' in p1 or '?' in p1 or '[' in p1):
+				start = len(name) - len(p1)
+				return start >= 0 and name[start:] = p1
+			for i in range(i, len(name) + 1):
+				if fnmatch1(name[i:], p1):
+					return 1
+			return 0
 		elif c = '?':
 			if len(name) <= i : return 0
 		elif c = '[':
-			return 0 # XXX
+			c, rest = name[i], name[i+1:]
+			i, n = i+1, len(pat) - 1
+			match = 0
+			exclude = 0
+			if i < n and pat[i] = '!':
+				exclude = 1
+				i = i+1
+			while i < n:
+				if pat[i] = c: match = 1
+				i = i+1
+				if i >= n or pat[i] = ']':
+					break
+				if pat[i] = '-':
+					i = i+1
+					if i >= n or pat[i] = ']':
+						break
+					match = (pat[i-2] <= c <= pat[i])
+					i = i+1
+			if match = exclude:
+				return 0
+			return fnmatch1(rest, pat[i+1:])
 		else:
 			if name[i:i+1] <> c:
 				return 0