1 18 19 package com.knowgate.jcifs.http; 20 21 import java.util.Enumeration ; 22 import java.util.LinkedList ; 23 import java.util.ListIterator ; 24 import java.util.Date ; 25 import java.util.GregorianCalendar ; 26 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.PrintWriter ; 30 31 import javax.servlet.*; 32 import javax.servlet.http.*; 33 34 import java.text.SimpleDateFormat ; 35 import java.net.UnknownHostException ; 36 37 import com.knowgate.jcifs.Config; 38 import com.knowgate.jcifs.UniAddress; 39 import com.knowgate.jcifs.ntlmssp.*; 40 import com.knowgate.jcifs.smb.SmbFile; 41 import com.knowgate.jcifs.smb.SmbFileInputStream; 42 import com.knowgate.jcifs.smb.NtlmPasswordAuthentication; 43 import com.knowgate.jcifs.smb.SmbException; 44 import com.knowgate.jcifs.smb.SmbAuthException; 45 import com.knowgate.jcifs.smb.SmbSession; 46 import com.knowgate.jcifs.smb.DfsReferral; 47 import com.knowgate.jcifs.netbios.NbtAddress; 48 import com.knowgate.jcifs.util.MimeMap; 49 50 import com.knowgate.misc.Base64Decoder; 51 52 61 62 public class NetworkExplorer extends HttpServlet { 63 64 private MimeMap mimeMap; 65 private String style; 66 private NtlmSsp ntlmSsp; 67 private boolean credentialsSupplied; 68 private boolean enableBasic; 69 private boolean insecureBasic; 70 private String realm, defaultDomain; 71 72 public void init() throws ServletException { 73 InputStream is; 74 StringBuffer sb = new StringBuffer (); 75 byte[] buf = new byte[1024]; 76 int n; 77 String name; 78 79 Config.setProperty( "jcifs.smb.client.soTimeout", "600000" ); 80 Config.setProperty( "jcifs.smb.client.attrExpirationPeriod", "300000" ); 81 82 Enumeration e = getInitParameterNames(); 83 while( e.hasMoreElements() ) { 84 name = (String )e.nextElement(); 85 if( name.startsWith( "jcifs." )) { 86 Config.setProperty( name, getInitParameter( name )); 87 } 88 } 89 90 if( Config.getProperty( "jcifs.smb.client.username" ) == null ) { 91 ntlmSsp = new NtlmSsp(); 92 } else { 93 credentialsSupplied = true; 94 } 95 96 try { 97 mimeMap = new MimeMap(); 98 is = getClass().getClassLoader().getResourceAsStream( "jcifs/http/ne.css" ); 99 while(( n = is.read( buf )) != -1 ) { 100 sb.append( new String ( buf, 0, n, "ISO8859_1" )); 101 } 102 style = sb.toString(); 103 } catch( IOException ioe ) { 104 throw new ServletException( ioe.getMessage() ); 105 } 106 107 enableBasic = Config.getBoolean("jcifs.http.enableBasic", false ); 108 insecureBasic = Config.getBoolean("jcifs.http.insecureBasic", false ); 109 realm = Config.getProperty("jcifs.http.basicRealm"); 110 if (realm == null) realm = "jCIFS"; 111 defaultDomain = Config.getProperty("jcifs.smb.client.domain"); 112 } 113 114 protected void doFile( HttpServletRequest req, 115 HttpServletResponse resp, SmbFile file ) throws IOException { 116 byte[] buf = new byte[8192]; 117 SmbFileInputStream in; 118 ServletOutputStream out; 119 String url, type; 120 int n; 121 122 in = new SmbFileInputStream( file ); 123 out = resp.getOutputStream(); 124 url = file.getPath(); 125 126 resp.setContentType( "text/plain" ); 127 128 if(( n = url.lastIndexOf( '.' )) > 0 && 129 ( type = url.substring( n + 1 )) != null && 130 type.length() > 1 && type.length() < 6 ) { 131 resp.setContentType( mimeMap.getMimeType( type )); 132 } 133 resp.setHeader( "Content-Length", file.length() + "" ); 134 resp.setHeader( "Accept-Ranges", "Bytes" ); 135 136 while(( n = in.read( buf )) != -1 ) { 137 out.write( buf, 0, n ); 138 } 139 } 140 protected int compareNames( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 141 if( f1.isDirectory() != f2.isDirectory() ) { 142 return f1.isDirectory() ? -1 : 1; 143 } 144 return f1name.compareToIgnoreCase( f2.getName() ); 145 } 146 protected int compareSizes( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 147 long diff; 148 149 if( f1.isDirectory() != f2.isDirectory() ) { 150 return f1.isDirectory() ? -1 : 1; 151 } 152 if( f1.isDirectory() ) { 153 return f1name.compareToIgnoreCase( f2.getName() ); 154 } 155 diff = f1.length() - f2.length(); 156 if( diff == 0 ) { 157 return f1name.compareToIgnoreCase( f2.getName() ); 158 } 159 return diff > 0 ? -1 : 1; 160 } 161 protected int compareTypes( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 162 String f2name, t1, t2; 163 int i; 164 165 if( f1.isDirectory() != f2.isDirectory() ) { 166 return f1.isDirectory() ? -1 : 1; 167 } 168 f2name = f2.getName(); 169 if( f1.isDirectory() ) { 170 return f1name.compareToIgnoreCase( f2name ); 171 } 172 i = f1name.lastIndexOf( '.' ); 173 t1 = i == -1 ? "" : f1name.substring( i + 1 ); 174 i = f2name.lastIndexOf( '.' ); 175 t2 = i == -1 ? "" : f2name.substring( i + 1 ); 176 177 i = t1.compareToIgnoreCase( t2 ); 178 if( i == 0 ) { 179 return f1name.compareToIgnoreCase( f2name ); 180 } 181 return i; 182 } 183 protected int compareDates( SmbFile f1, String f1name, SmbFile f2 ) throws IOException { 184 if( f1.isDirectory() != f2.isDirectory() ) { 185 return f1.isDirectory() ? -1 : 1; 186 } 187 if( f1.isDirectory() ) { 188 return f1name.compareToIgnoreCase( f2.getName() ); 189 } 190 return f1.lastModified() > f2.lastModified() ? -1 : 1; 191 } 192 protected void doDirectory( HttpServletRequest req, HttpServletResponse resp, SmbFile dir ) throws IOException { 193 PrintWriter out; 194 SmbFile[] dirents; 195 SmbFile f; 196 int i, j, len, maxLen, dirCount, fileCount, sort; 197 String str, name, path, fmt; 198 LinkedList sorted; 199 ListIterator iter; 200 SimpleDateFormat sdf = new SimpleDateFormat ( "MM/d/yy h:mm a" ); 201 GregorianCalendar cal = new GregorianCalendar (); 202 203 sdf.setCalendar( cal ); 204 205 dirents = dir.listFiles(); 206 sorted = new LinkedList (); 207 if(( fmt = req.getParameter( "fmt" )) == null ) { 208 fmt = "col"; 209 } 210 sort = 0; 211 if(( str = req.getParameter( "sort" )) == null || str.equals( "name" )) { 212 sort = 0; 213 } else if( str.equals( "size" )) { 214 sort = 1; 215 } else if( str.equals( "type" )) { 216 sort = 2; 217 } else if( str.equals( "date" )) { 218 sort = 3; 219 } 220 dirCount = fileCount = 0; 221 maxLen = 28; 222 for( i = 0; i < dirents.length; i++ ) { 223 try { 224 if( dirents[i].getType() == SmbFile.TYPE_NAMED_PIPE ) { 225 continue; 226 } 227 } catch( SmbAuthException sae ) { 228 } catch( SmbException se ) { 229 if( se.getNtStatus() != se.NT_STATUS_UNSUCCESSFUL ) { 230 throw se; 231 } 232 } 233 if( dirents[i].isDirectory() ) { 234 dirCount++; 235 } else { 236 fileCount++; 237 } 238 239 name = dirents[i].getName(); 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 ( Base64Decoder.decodeToBytes(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 |