1 18 19 package jcifs.http; 20 21 import java.io.*; 22 import javax.servlet.*; 23 import javax.servlet.http.*; 24 import java.util.*; 25 import java.text.SimpleDateFormat ; 26 import java.net.UnknownHostException ; 27 import jcifs.*; 28 import jcifs.http.*; 29 import jcifs.smb.*; 30 import jcifs.netbios.NbtAddress; 31 import jcifs.util.MimeMap; 32 import jcifs.util.Base64; 33 import jcifs.util.LogStream; 34 35 41 42 public class NetworkExplorer extends HttpServlet { 43 44 private static LogStream log = LogStream.getInstance(); 45 46 private MimeMap mimeMap; 47 private String style; 48 private NtlmSsp ntlmSsp; 49 private boolean credentialsSupplied; 50 private boolean enableBasic; 51 private boolean insecureBasic; 52 private String realm, defaultDomain; 53 54 public void init() throws ServletException { 55 InputStream is; 56 StringBuffer sb = new StringBuffer (); 57 byte[] buf = new byte[1024]; 58 int n, level; 59 String name; 60 61 Config.setProperty( "jcifs.smb.client.soTimeout", "600000" ); 62 Config.setProperty( "jcifs.smb.client.attrExpirationPeriod", "300000" ); 63 64 Enumeration e = getInitParameterNames(); 65 while( e.hasMoreElements() ) { 66 name = (String )e.nextElement(); 67 if( name.startsWith( "jcifs." )) { 68 Config.setProperty( name, getInitParameter( name )); 69 } 70 } 71 72 if( Config.getProperty( "jcifs.smb.client.username" ) == null ) { 73 ntlmSsp = new NtlmSsp(); 74 } else { 75 credentialsSupplied = true; 76 } 77 78 try { 79 mimeMap = new MimeMap(); 80 is = getClass().getClassLoader().getResourceAsStream( "jcifs/http/ne.css" ); 81 while(( n = is.read( buf )) != -1 ) { 82 sb.append( new String ( buf, 0, n, "ISO8859_1" )); 83 } 84 style = sb.toString(); 85 } catch( IOException ioe ) { 86 throw new ServletException( ioe.getMessage() ); 87 } 88 89 enableBasic = Config.getBoolean("jcifs.http.enableBasic", false ); 90 insecureBasic = Config.getBoolean("jcifs.http.insecureBasic", false ); 91 realm = Config.getProperty("jcifs.http.basicRealm"); 92 if (realm == null) realm = "jCIFS"; 93 defaultDomain = Config.getProperty("jcifs.smb.client.domain"); 94 95 if(( level = Config.getInt( "jcifs.util.loglevel", -1 )) != -1 ) { 96 LogStream.setLevel( level ); 97 } 98 if( log.level > 2 ) { 99 try { 100 Config.store( log, "JCIFS PROPERTIES" ); 101 } catch( IOException ioe ) { 102 } 103 } 104 } 105 106 protected void doFile( HttpServletRequest req, 107 HttpServletResponse resp, SmbFile file ) throws IOException { 108 byte[] buf = new byte[8192]; 109 SmbFileInputStream in; 110 ServletOutputStream out; 111 String url, type; 112 int n; 113 114 in = new SmbFileInputStream( file ); 115 out = resp.getOutputStream(); 116 url = file.getPath(); 117 118 resp.setContentType( "text/plain" ); 119 120 if(( n = url.lastIndexOf( '.' )) > 0 && 121 ( type = url.substring( n + 1 )) != null && 122 type.length() > 1 && type.length() < 6 ) { 123 resp.setContentType( mimeMap.getMimeType( type )); 124 } 125 resp.setHeader( "Content-Length", file.length() + "" ); 126 resp.setHeader( "Accept-Ranges", "Bytes" ); 127 128 while(( n = in.read( buf )) != -1 ) { 129 out.write( buf, 0, n ); 130 } 131 } 132 protected int compareNames( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 133 if( f1.isDirectory() != f2.isDirectory() ) { 134 return f1.isDirectory() ? -1 : 1; 135 } 136 return f1name.compareToIgnoreCase( f2.getName() ); 137 } 138 protected int compareSizes( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 139 long diff; 140 141 if( f1.isDirectory() != f2.isDirectory() ) { 142 return f1.isDirectory() ? -1 : 1; 143 } 144 if( f1.isDirectory() ) { 145 return f1name.compareToIgnoreCase( f2.getName() ); 146 } 147 diff = f1.length() - f2.length(); 148 if( diff == 0 ) { 149 return f1name.compareToIgnoreCase( f2.getName() ); 150 } 151 return diff > 0 ? -1 : 1; 152 } 153 protected int compareTypes( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 154 String f2name, t1, t2; 155 int i; 156 157 if( f1.isDirectory() != f2.isDirectory() ) { 158 return f1.isDirectory() ? -1 : 1; 159 } 160 f2name = f2.getName(); 161 if( f1.isDirectory() ) { 162 return f1name.compareToIgnoreCase( f2name ); 163 } 164 i = f1name.lastIndexOf( '.' ); 165 t1 = i == -1 ? "" : f1name.substring( i + 1 ); 166 i = f2name.lastIndexOf( '.' ); 167 t2 = i == -1 ? "" : f2name.substring( i + 1 ); 168 169 i = t1.compareToIgnoreCase( t2 ); 170 if( i == 0 ) { 171 return f1name.compareToIgnoreCase( f2name ); 172 } 173 return i; 174 } 175 protected int compareDates( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 176 if( f1.isDirectory() != f2.isDirectory() ) { 177 return f1.isDirectory() ? -1 : 1; 178 } 179 if( f1.isDirectory() ) { 180 return f1name.compareToIgnoreCase( f2.getName() ); 181 } 182 return f1.lastModified() > f2.lastModified() ? -1 : 1; 183 } 184 protected void doDirectory( HttpServletRequest req, HttpServletResponse resp, SmbFile dir ) throws IOException { 185 PrintWriter out; 186 SmbFile[] dirents; 187 SmbFile f; 188 int i, j, len, maxLen, dirCount, fileCount, sort; 189 String str, name, path, fmt; 190 LinkedList sorted; 191 ListIterator iter; 192 SimpleDateFormat sdf = new SimpleDateFormat ( "MM/d/yy h:mm a" ); 193 GregorianCalendar cal = new GregorianCalendar(); 194 195 sdf.setCalendar( cal ); 196 197 dirents = dir.listFiles(); 198 if( log.level > 2 ) 199 log.println( dirents.length + " items listed" ); 200 sorted = new LinkedList(); 201 if(( fmt = req.getParameter( "fmt" )) == null ) { 202 fmt = "col"; 203 } 204 sort = 0; 205 if(( str = req.getParameter( "sort" )) == null || str.equals( "name" )) { 206 sort = 0; 207 } else if( str.equals( "size" )) { 208 sort = 1; 209 } else if( str.equals( "type" )) { 210 sort = 2; 211 } else if( str.equals( "date" )) { 212 sort = 3; 213 } 214 dirCount = fileCount = 0; 215 maxLen = 28; 216 for( i = 0; i < dirents.length; i++ ) { 217 try { 218 if( dirents[i].getType() == SmbFile.TYPE_NAMED_PIPE ) { 219 continue; 220 } 221 } catch( SmbAuthException sae ) { 222 if( log.level > 2 ) 223 sae.printStackTrace( log ); 224 } catch( SmbException se ) { 225 if( log.level > 2 ) 226 se.printStackTrace( log ); 227 if( se.getNtStatus() != se.NT_STATUS_UNSUCCESSFUL ) { 228 throw se; 229 } 230 } 231 if( dirents[i].isDirectory() ) { 232 dirCount++; 233 } else { 234 fileCount++; 235 } 236 237 name = dirents[i].getName(); 238 if( log.level > 3 ) 239 log.println( i + ": " + name ); 240 len = name.length(); 241 if( len > maxLen ) { 242 maxLen = len; 243 } 244 245 iter = sorted.listIterator(); 246 for( j = 0; iter.hasNext(); j++ ) { 247 if( sort == 0 ) { 248 if( compareNames( dirents[i], name, (SmbFile)iter.next() ) < 0 ) { 249 break; 250 } 251 } else if( sort == 1 ) { 252 if( compareSizes( dirents[i], name, (SmbFile)iter.next() ) < 0 ) { 253 break; 254 } 255 } else if( sort == 2 ) { 256 if( compareTypes( dirents[i], name, (SmbFile)iter.next() ) < 0 ) { 257 break; 258 } 259 } else if( sort == 3 ) { 260 if( compareDates( dirents[i], name, (SmbFile)iter.next() ) < 0 ) { 261 break; 262 } 263 } 264 } 265 sorted.add( j, dirents[i] ); 266 } 267 if( maxLen > 50 ) { 268 maxLen = 50; 269 } 270 maxLen *= 9; 271 272 out = resp.getWriter(); 273 274 resp.setContentType( "text/html" ); 275 276 out.println( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">" ); 277 out.println( "<html><head><title>Network Explorer</title>" ); 278 out.println( "<meta HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" ); 279 out.println( "<style TYPE=\"text/css\">" ); 280 281 out.println( style ); 282 283 if( dirents.length < 200 ) { 284 out.println( " a:hover {" ); 285 out.println( " background: #a2ff01;" ); 286 out.println( " }" ); 287 } 288 289 out.println( "</STYLE>" ); 290 out.println( "</head><body>" ); 291 292 out.print( "<a class=\"sort\" style=\"width: " + maxLen + ";\" HREF=\"?fmt=detail&sort=name\">Name</a>" ); 293 out.println( "<a class=\"sort\" HREF=\"?fmt=detail&sort=size\">Size</a>" ); 294 out.println( "<a class=\"sort\" HREF=\"?fmt=detail&sort=type\">Type</a>" ); 295 out.println( "<a class=\"sort\" style=\"width: 180\" HREF=\"?fmt=detail&sort=date\">Modified</a><br clear='all'><p>" ); 296 297 path = dir.getCanonicalPath(); 298 299 if( path.length() < 7 ) { 300 out.println( "<b><big>smb://</big></b><br>" ); 301 path = "."; 302 } else { 303 out.println( "<b><big>" + path + "</big></b><br>" ); 304 path = "../"; 305 } 306 out.println( (dirCount + fileCount) + " objects (" + dirCount + " directories, " + fileCount + " files)<br>" ); 307 out.println( "<b><a class=\"plain\" HREF=\".\">normal</a> | <a class=\"plain\" HREF=\"?fmt=detail\">detailed</a></b>" ); 308 out.println( "<p><table border='0' cellspacing='0' cellpadding='0'><tr><td>" ); 309 310 out.print( "<A style=\"width: " + maxLen ); 311 out.print( "; height: 18;\" HREF=\"" ); 312 out.print( path ); 313 out.println( "\"><b>↑</b></a>" ); 314 if( fmt.equals( "detail" )) { 315 out.println( "<br clear='all'>" ); 316 } 317 318 if( path.length() == 1 || dir.getType() != SmbFile.TYPE_WORKGROUP ) { 319 path = ""; 320 } 321 322 iter = sorted.listIterator(); 323 while( iter.hasNext() ) { 324 f = (SmbFile)iter.next(); 325 name = f.getName(); 326 327 if( fmt.equals( "detail" )) { 328 out.print( "<A style=\"width: " + maxLen ); 329 out.print( "; height: 18;\" HREF=\"" ); 330 out.print( path ); 331 out.print( name ); 332 333 if( f.isDirectory() ) { 334 out.print( "?fmt=detail\"><b>" ); 335 out.print( name ); 336 out.print( "</b></a>" ); 337 } else { 338 out.print( "\"><b>" ); 339 out.print( name ); 340 out.print( "</b></a><div align='right'>" ); 341 out.print( (f.length() / 1024) + " KB </div><div>" ); 342 i = name.lastIndexOf( '.' ) + 1; 343 if( i > 1 && (name.length() - i) < 6 ) { 344 out.print( name.substring( i ).toUpperCase() + "</div class='ext'>" ); 345 } else { 346 out.print( " </div>" ); 347 } 348 out.print( "<div style='width: 180'>" ); 349 out.print( sdf.format( new Date( f.lastModified() ))); 350 out.print( "</div>" ); 351 } 352 out.println( "<br clear='all'>" ); 353 } else { 354 out.print( "<A style=\"width: " + maxLen ); 355 if( f.isDirectory() ) { 356 out.print( "; height: 18;\" HREF=\"" ); 357 out.print( path ); 358 out.print( name ); 359 out.print( "\"><b>" ); 360 out.print( name ); 361 out.print( "</b></a>" ); 362 } else { 363 out.print( ";\" HREF=\"" ); 364 out.print( path ); 365 out.print( name ); 366 out.print( "\"><b>" ); 367 out.print( name ); 368 out.print( "</b><br><small>" ); 369 out.print( (f.length() / 1024) + "KB <br>" ); 370 out.print( sdf.format( new Date( f.lastModified() ))); 371 out.print( "</small>" ); 372 out.println( "</a>" ); 373 } 374 } 375 } 376 377 out.println( "</td></tr></table>" ); 378 out.println( "</BODY></HTML>" ); 379 out.close(); 380 } 381 private String parseServerAndShare( String pathInfo ) { 382 char[] out = new char[256]; 383 char ch; 384 int len, p, i; 385 386 if( pathInfo == null ) { 387 return null; 388 } 389 len = pathInfo.length(); 390 391 p = i = 0; 392 while( p < len && pathInfo.charAt( p ) == '/' ) { 393 p++; 394 } 395 if( p == len ) { 396 return null; 397 } 398 399 400 while ( p < len && ( ch = pathInfo.charAt( p )) != '/' ) { 401 out[i++] = ch; 402 p++; 403 } 404 while( p < len && pathInfo.charAt( p ) == '/' ) { 405 p++; 406 } 407 if( p < len ) { 408 out[i++] = '/'; 409 do { 410 out[i++] = (ch = pathInfo.charAt( p++ )); 411 } while( p < len && ch != '/' ); 412 } 413 return new String ( out, 0, i ); 414 } 415 public void doGet( HttpServletRequest req, 416 HttpServletResponse resp ) throws IOException, ServletException { 417 UniAddress dc; 418 String msg, pathInfo, server = null; 419 boolean offerBasic, possibleWorkgroup = true; 420 NtlmPasswordAuthentication ntlm = null; 421 HttpSession ssn = req.getSession( false ); 422 423 if(( pathInfo = req.getPathInfo() ) != null ) { 424 int i; 425 server = parseServerAndShare( pathInfo ); 426 if( server != null && ( i = server.indexOf( '/' )) > 0 ) { 427 server = server.substring( 0, i ).toLowerCase(); 428 possibleWorkgroup = false; 429 } 430 } 431 432 msg = req.getHeader( "Authorization" ); 433 offerBasic = enableBasic && (insecureBasic || req.isSecure()); 434 435 if( msg != null && (msg.startsWith( "NTLM " ) || 436 (offerBasic && msg.startsWith("Basic ")))) { 437 438 if( msg.startsWith("NTLM ")) { 439 byte[] challenge; 440 441 if( pathInfo == null || server == null ) { 442 String mb = NbtAddress.getByName( NbtAddress.MASTER_BROWSER_NAME, 0x01, null ).getHostAddress(); 443 dc = UniAddress.getByName( mb ); 444 } else { 445 dc = UniAddress.getByName( server, possibleWorkgroup ); 446 } 447 448 req.getSession(); 449 challenge = SmbSession.getChallenge( dc ); 450 if(( ntlm = NtlmSsp.authenticate( req, resp, challenge )) == null ) { 451 return; 452 } 453 } else { 454 String auth = new String ( Base64.decode( msg.substring(6) ), "US-ASCII" ); 455 int index = auth.indexOf( ':' ); 456 String user = (index != -1) ? auth.substring(0, index) : auth; 457 String password = (index != -1) ? auth.substring(index + 1) : ""; 458 index = user.indexOf('\\'); 459 if (index == -1) index = user.indexOf('/'); 460 String domain = (index != -1) ? user.substring(0, index) : defaultDomain; 461 user = (index != -1) ? user.substring(index + 1) : user; 462 ntlm = new NtlmPasswordAuthentication(domain, user, password); 463 } 464 465 req.getSession().setAttribute( "npa-" + server, ntlm ); 466 467 } else if( !credentialsSupplied ) { 468 if( ssn != null ) { 469 ntlm = (NtlmPasswordAuthentication)ssn.getAttribute( "npa-" + server ); 470 } 471 if( ntlm == null ) { 472 resp.setHeader( "WWW-Authenticate", "NTLM" ); 473 if (offerBasic) { 474 resp.addHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\""); 475 } 476 resp.setHeader( "Connection", "close" ); 477 resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED ); 478 resp.flushBuffer(); 479 return; 480 } 481 } 482 483 try { 484 SmbFile file; 485 486 if( ntlm != null ) { 487 file = new SmbFile( "smb:/" + pathInfo , ntlm ); 488 } else if( server == null ) { 489 file = new SmbFile( "smb://" ); 490 } else { 491 file = new SmbFile( "smb:/" + pathInfo ); 492 } 493 494 if( file.isDirectory() ) { 495 doDirectory( req, resp, file ); 496 } else { 497 doFile( req, resp, file ); 498 } 499 } catch( SmbAuthException sae ) { 500 if( ssn != null ) { 501 ssn.removeAttribute( "npa-" + server ); 502 } 503 if( sae.getNtStatus() == sae.NT_STATUS_ACCESS_VIOLATION ) { 504 507 resp.sendRedirect( req.getRequestURL().toString() ); 508 return; 509 } 510 resp.setHeader( "WWW-Authenticate", "NTLM" ); 511 if (offerBasic) { 512 resp.addHeader( "WWW-Authenticate", "Basic realm=\"" + realm + "\""); 513 } 514 resp.setHeader( "Connection", "close" ); 515 resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED ); 516 resp.flushBuffer(); 517 return; 518 } catch( DfsReferral dr ) { 519 StringBuffer redir = req.getRequestURL(); 520 String qs = req.getQueryString(); 521 redir = new StringBuffer ( redir.substring( 0, redir.length() - req.getPathInfo().length() )); 522 redir.append( dr.node.replace( '\\', '/' )); 523 redir.append( '/' ); 524 if( qs != null ) { 525 redir.append( req.getQueryString() ); 526 } 527 resp.sendRedirect( redir.toString() ); 528 resp.flushBuffer(); 529 return; 530 } 531 } 532 } 533 534 | Popular Tags |