first commit

This commit is contained in:
ouburikou
2018-02-05 18:59:21 +08:00
commit bb00973025
957 changed files with 231677 additions and 0 deletions

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
demo-shiro-interface/target/
demo-shiro-service/target/
demo-shiro-web/target/
springboot-shiro-configure/target/
.classpath
.idea
.project
.settings
/bin
*/bin
*.iml
*/*.iml

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shiro-springboot-demo</artifactId>
<groupId>demo.xinwin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-shiro-interface</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>demo.xinwin</groupId>
<artifactId>springboot-shiro-configure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${springboot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.github.calimero</groupId>
<artifactId>calimero-core</artifactId>
<version>${calimero.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.3</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,28 @@
package com.xinwei.common.page;
import java.io.Serializable;
public class Columns implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String data;
private boolean searchable;
public boolean isSearchable() {
return searchable;
}
public void setSearchable(boolean searchable) {
this.searchable = searchable;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

View File

@@ -0,0 +1,138 @@
package com.xinwei.common.page;
import java.util.Collection;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;
import com.google.common.collect.Lists;
import com.xinwei.utils.Collections3;
import com.xinwei.utils.SearchFilter;
public class DynamicSpecifications {
public static <T> Specification<T> bySearchFilter(final Collection<SearchFilter> filters, final Class<T> clazz) {
return new Specification<T>() {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (Collections3.isNotEmpty(filters)) {
List<Predicate> predicates = Lists.newArrayList();
for (SearchFilter filter : filters) {
// nested path translate, 如Task的名为"user.name"的filedName, 转换为Task.user.name属性
String[] names = StringUtils.split(filter.fieldName, ".");
Path expression = root.get(names[0]);
for (int i = 1; i < names.length; i++) {
expression = expression.get(names[i]);
}
// logic operator
switch (filter.operator) {
case NEQ:
predicates.add(builder.notEqual(expression, filter.value));
break;
case EQ:
predicates.add(builder.equal(expression, filter.value));
break;
case LIKE:
predicates.add(builder.like(expression, "%" + filter.value + "%"));
break;
case GT:
predicates.add(builder.greaterThan(expression, (Comparable) filter.value));
break;
case LT:
predicates.add(builder.lessThan(expression, (Comparable) filter.value));
break;
case GTE:
predicates.add(builder.greaterThanOrEqualTo(expression, (Comparable) filter.value));
break;
case LTE:
predicates.add(builder.lessThanOrEqualTo(expression, (Comparable) filter.value));
break;
case ISNULL:
predicates.add(builder.isNull(expression));
break;
case ISNOTNULL:
predicates.add(builder.isNotNull(expression));
break;
}
}
// 将所有条件用 and 联合起来
if (predicates.size() > 0) {
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}
return builder.conjunction();
}
};
}
public static <T> Specification<T> bySearchFilterOr(final Collection<SearchFilter> filters, final Class<T> clazz) {
return new Specification<T>() {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (Collections3.isNotEmpty(filters)) {
List<Predicate> predicates = Lists.newArrayList();
for (SearchFilter filter : filters) {
// nested path translate, 如Task的名为"user.name"的filedName, 转换为Task.user.name属性
String[] names = StringUtils.split(filter.fieldName, ".");
Path expression = root.get(names[0]);
for (int i = 1; i < names.length; i++) {
expression = expression.get(names[i]);
}
// logic operator
switch (filter.operator) {
case NEQ:
predicates.add(builder.notEqual(expression, filter.value));
break;
case EQ:
predicates.add(builder.equal(expression, filter.value));
break;
case LIKE:
predicates.add(builder.like(expression, "%" + filter.value + "%"));
break;
case GT:
predicates.add(builder.greaterThan(expression, (Comparable) filter.value));
break;
case LT:
predicates.add(builder.lessThan(expression, (Comparable) filter.value));
break;
case GTE:
predicates.add(builder.greaterThanOrEqualTo(expression, (Comparable) filter.value));
break;
case LTE:
predicates.add(builder.lessThanOrEqualTo(expression, (Comparable) filter.value));
break;
case ISNULL:
predicates.add(builder.isNull(expression));
break;
case ISNOTNULL:
predicates.add(builder.isNotNull(expression));
break;
}
}
// 将所有条件用 or 联合起来
if (predicates.size() > 0) {
return builder.or(predicates.toArray(new Predicate[predicates.size()]));
}
}
return builder.conjunction();
}
};
}
}

View File

@@ -0,0 +1,37 @@
package com.xinwei.common.page;
import java.io.Serializable;
public class Order implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int column;//排序字段属性编号012
private String columnName;//排序字段属性名称
private String dir;
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
public String getDir() {
return dir;
}
public void setDir(String dir) {
this.dir = dir;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
}

View File

@@ -0,0 +1,305 @@
package com.xinwei.common.page;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import com.github.pagehelper.PageInfo;
public class Pagination<T> extends PageInfo<T> {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
public Pagination() {
}
public Pagination(List<T> list) {
super(list);
}
private int draw;
private Search search;
private List<Order> order;
private List<Columns> columns;
//begin.................................
private String extra_search;
public String getExtra_search() {
return extra_search;
}
public void setExtra_search(String extra_search) {
this.extra_search = extra_search;
}
//将查询条件转换到实体类对应的字段中.
public static <T> T queryCondtion2Entry(T t, Pagination<T> page) {
String seachstring = page.getExtra_search();
//判断是否为空,如果为空直接返回
if(null==seachstring){
return t;
}
if("".equals(seachstring.trim())){
return t;
}
//这里添加一下 编码解码 看看问题.
try {
seachstring = java.net.URLDecoder.decode(seachstring, "utf-8");
} catch (Exception e) {
}
//这里添加一下 编码解码 看看问题.
//max=1&min=0
String[] split = seachstring.split("&");
for (String query : split) {
if (query!=null) {
String[] keyAndValue = query.split("=");
if(keyAndValue!=null){
if(keyAndValue.length==1){
continue;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Field field = ReflectionUtils.findField(t.getClass(), keyAndValue[0]);
// 修改访问控制权限
boolean accessFlag = field.isAccessible();
field.setAccessible(true);
if (null != field) {
//暂时添加 Integer 和 String 的类型判断.
String value =keyAndValue[1];
if (field.getType() == Integer.class) {
try {
Integer.parseInt(value);
ReflectionUtils.setField(field, t, Integer.parseInt(value));
} catch (NumberFormatException e) {
}
} else if (field.getType() == Date.class) {
// 如果字段是时间类型
} else {
ReflectionUtils.setField(field, t, value);
}
}
// 恢复访问控制权限
field.setAccessible(accessFlag);
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
}
}
}
return t;
}
//end.....................................
public int getDraw() {
return draw;
}
public void setDraw(int draw) {
this.draw = draw;
}
public int getStart() {
return super.getStartRow();
}
public void setStart(int start) {
super.setStartRow(start);
}
public int getLength() {
return super.getPageSize();
}
public void setLength(int length) {
super.setPageSize(length);
}
public int getRecordsTotal() {
return (int) super.getTotal();
}
public int getRecordsFiltered() {
return (int) super.getTotal();
}
public void setOrder(List<Order> order) {
this.order = order;
}
public List<T> getData() {
return super.getList();
}
public void setSearch(Search search) {
this.search = search;
}
public void setColumns(List<Columns> columns) {
this.columns = columns;
}
public List<Order> getOrder() {
return order;
}
public Search getSearch() {
return search;
}
public List<Columns> getColumns() {
return columns;
}
public static <T> T dataTable2Entry(T t, Pagination<T> page) {
List<Order> odrs = new ArrayList<Order>();
List<Columns> cols = page.getColumns();
if (null != page.getOrder())
for (Order odr : page.getOrder()) {
String cname = cols.get(odr.getColumn()).getData();
if (null != cname && !"".equals(cname)) {
Order o = new Order();
o.setDir(cname + "&&" + odr.getDir()); // result: devicename
// desc
o.setColumn(odr.getColumn());
odrs.add(o);
}
}
page.setOrder(odrs);
if (null != cols)
for (Columns col : cols) {
String cname = col.getData();// columsname字段名
// col.isSearchable();// 是否搜索
if (!StringUtils.isEmpty(cname) && col.isSearchable()) {
Field field = ReflectionUtils.findField(t.getClass(), cname);
field.setAccessible(true);
if (null != field) {
if (field.getType() == Integer.class) {
if (!"".equals(page.getSearch().getValue())) {
String value = page.getSearch().getValue();
try {
Integer.parseInt(value);
ReflectionUtils.setField(field, t, Integer.parseInt(value));
} catch (NumberFormatException e) {
}
}
} else if (field.getType() == Date.class) {
// 如果字段是时间类型
} else {
ReflectionUtils.setField(field, t, page.getSearch().getValue());
}
}
}
}
return t;
}
public static <T> Sort dataTableOrder(Pagination<T> page,Sort sort, List<String> properties) {
String orderBy = "";
/* for (int i = 0; null != page.getOrder() && i < page.getOrder().size(); i++) {
Order order = page.getOrder().get(i);
orderBy += order.getDir();
if (i < page.getOrder().size() - 1) {
orderBy += ",";
}
}*/
for (int i = 0; null != page.getOrder() && i < page.getOrder().size(); i++) {
Order order = page.getOrder().get(i);
orderBy = order.getDir();
if(orderBy!=null&&!orderBy.equals("")){
String orderbystr = orderBy.split("&&")[0];
System.out.println("orderbystr="+orderbystr);
String sortStr = orderBy.split("&&")[1];
properties.clear();
properties.add(orderbystr);
sort = new Sort(Direction.fromString(sortStr), properties);
}
}
return sort;
}
//begin ...........................................................
public static <T> Sort getOrderBydataTable(Pagination<T> page) {
//Sort sort=new Sort();
List<org.springframework.data.domain.Sort.Order> orderlist=new ArrayList<org.springframework.data.domain.Sort.Order>();
for (int i = 0; null != page.getOrder() && i < page.getOrder().size(); i++) {
Order order = page.getOrder().get(i);
Columns columns = page.getColumns().get(order.getColumn());
if("asc".equals(order.getDir())){
orderlist.add(new org.springframework.data.domain.Sort.Order(Direction.ASC, columns.getData()));
}else{
orderlist.add(new org.springframework.data.domain.Sort.Order(Direction.DESC, columns.getData()));
}
}
if(orderlist!=null&&orderlist.size()>0){
Sort sort=new Sort(orderlist);
return sort;
}
return null;
}
//为什么只有一个 排序呢, datatable现在就是 排序一个.
public static <T> org.springframework.data.domain.Sort.Order getStringOrderBydataTable(Pagination<T> page) {
List<org.springframework.data.domain.Sort.Order> orderlist=new ArrayList<org.springframework.data.domain.Sort.Order>();
org.springframework.data.domain.Sort.Order sortorder=null;
for (int i = 0; null != page.getOrder() && i < page.getOrder().size(); i++) {
Order order = page.getOrder().get(i);
Columns columns = page.getColumns().get(order.getColumn());
if("asc".equals(order.getDir())){
sortorder=new org.springframework.data.domain.Sort.Order(Direction.ASC, columns.getData());
break;
}else{
sortorder=new org.springframework.data.domain.Sort.Order(Direction.DESC, columns.getData());
break;
}
}
return sortorder;
}
//end ...........................................................
}

View File

@@ -0,0 +1,105 @@
package com.xinwei.common.page;
import java.io.Serializable;
import java.util.List;
/**
*
* <b>类名</b>PaginationResult.java<br>
* <p><b>标题</b>:中信国安 </p>
* <p><b>描述</b>
* DataTables 返回分页数据的 对象
* 实现Serializable 接口.
* </p>
* <p><b>版权声明</b>Copyright (c) 2016</p>
* <p><b>公司</b>:中信国安 </p>
* @author <font color='blue'>zhangzq</font>
* @version 1.0
* @date 2016年7月7日 下午2:09:03
* @param <T>
*/
public class PaginationResult<T> implements Serializable{
/** serialVersionUID */
private static final long serialVersionUID = 1L;
public PaginationResult() {
}
/**
* 暂时没有发现这个字段的含义.
* datatables 提示这是必须的字段,暂时保留.
*/
private int draw;
/**
* 经过查询条件查询的总个数.
* (一般情况下 默认和recordsTotal 保持一样就可以)
*/
private long recordsFiltered;
/**
* 查询的总个数
*/
private long recordsTotal;
/**
* 查询某页返回的数据.
*/
private List<T> data;
public int getDraw() {
return draw;
}
public void setDraw(int draw) {
this.draw = draw;
}
public long getRecordsFiltered() {
return recordsFiltered;
}
public void setRecordsFiltered(long recordsFiltered) {
this.recordsFiltered = recordsFiltered;
}
public long getRecordsTotal() {
return recordsTotal;
}
public void setRecordsTotal(long recordsTotal) {
this.recordsTotal = recordsTotal;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
}

View File

@@ -0,0 +1,29 @@
package com.xinwei.common.page;
import java.io.Serializable;
public class Search implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String value;
private boolean regex;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isRegex() {
return regex;
}
public void setRegex(boolean regex) {
this.regex = regex;
}
}

View File

@@ -0,0 +1,54 @@
package com.xinwei.common.page;
import java.util.Map;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import com.xinwei.utils.ReflectionUtils;
import com.xinwei.utils.SearchFilter;
public class SpecificationUtil<T> {
protected Class<T> entityClass;
public SpecificationUtil() {
this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
}
/**
* 创建分页请求.
*/
protected PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
Sort sort = null;
if ("auto".equals(sortType)) {
sort = new Sort(Direction.ASC, "id");
} else if (sortType != null && !"".equals(sortType) && !sortType.contains("_ASC")) {
sort = new Sort(Direction.DESC, sortType);
} else if(null != sortType && sortType.contains("_ASC")) {
sort = new Sort(Direction.ASC, sortType.split("_ASC")[0]);
}
return new PageRequest(pageNumber - 1, pagzSize, sort);
}
/**
* 创建动态查询条件组合.
*/
public Specification<T> buildSpecification(Map<String, Object> searchParams,String orAnd) {
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
Specification<T> spec=null;
if(orAnd.equals("or")){
spec = DynamicSpecifications.bySearchFilterOr(filters.values(), ReflectionUtils.getSuperClassGenricType(getClass()));
}else{
spec = DynamicSpecifications.bySearchFilter(filters.values(), ReflectionUtils.getSuperClassGenricType(getClass()));
}
return spec;
}
}

View File

@@ -0,0 +1,28 @@
package com.xinwei.service;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
public interface EntityService<T, PK extends Serializable> {
T get(PK var1);
void delete(PK var1);
void delete(Iterable<T> var1);
void delete(T var1);
void save(T var1);
Iterable<T> getAll();
Page<T> search(Map<String, Object> var1, int var2, int var3, String var4);
List<T> findAll(Map<String, Object> var1);
List<T> findAll(Map<String, Object> var1, Sort var2);
}

View File

@@ -0,0 +1,20 @@
package com.xinwei.service;
import java.util.List;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.shirofunction.ShiroRole;
public interface ShiroRoleService extends EntityService<ShiroRole, Long>{
public ShiroRole findByRoleName(String rolename);
public ShiroRole findById(Integer id);
public List<ShiroRole> findRoleList();
public PaginationResult<ShiroRole> findAllByPage(Pagination<ShiroRole> pagination);
}

View File

@@ -0,0 +1,39 @@
package com.xinwei.service;
import java.util.List;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.shirofunction.ShiroUser;
import com.xinwei.utils.ResponseJson;
public interface ShiroUserService extends EntityService<ShiroUser, Long>{
public ShiroUser findByUsername(String userName);
public List<ShiroUser> findList();
public PaginationResult<ShiroUser> findAllByPage(Pagination<ShiroUser> pagination);
public ResponseJson editUser(ShiroUser shiroUser);
public ResponseJson editUserRole(String username,String roles);
public ResponseJson del(String ids)throws Exception;
/**
* 用户审核
* @param userNameStr
* @return
*/
public ResponseJson audit(String userNameStr,String status) throws Exception;
public ShiroUser findByUsernameForUpdate(String username);
public ResponseJson addUser(ShiroUser shiroUser);
public ResponseJson checkNameOrEmallExist(ShiroUser shiroUser);
}

View File

@@ -0,0 +1,34 @@
package com.xinwei.shirofunction;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
/**
* 系统功能目录
* @author ouburikou
*
*/
@Entity
@Table(name = "shiro_function")
@Data
public class Function implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String functionName;
private Date createTime;
private Integer pid;
private String permissionName;//securityApply:templetUpload
}

View File

@@ -0,0 +1,22 @@
package com.xinwei.shirofunction;
import java.util.List;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.service.EntityService;
public interface FunctionService extends EntityService<Function, Long>{
public PaginationResult<Function> findAllByPage(Pagination<Function> pagination);
public List<Function> findList();
public Function findById(Integer id);
public Function findByPermissionName(String permissionName);
public Function findByPid(Integer pid);
public List<Function> findListByPid(Integer pid);
}

View File

@@ -0,0 +1,22 @@
package com.xinwei.shirofunction;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* 展示功能Tree时使用。
* @author ouburikou
*
*/
@Slf4j
@Data
public class FunctionTreeBean {
private Integer id;
private Integer pId;
private String name;
private boolean checked=false;
private boolean open=true;
}

View File

@@ -0,0 +1,10 @@
package com.xinwei.shirofunction;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.service.EntityService;
public interface RoleService extends EntityService<ShiroRole, Long>{
public PaginationResult<ShiroRole> findAllByPage(Pagination<ShiroRole> pagination);
}

View File

@@ -0,0 +1,87 @@
package com.xinwei.shirofunction;
import lombok.Data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "shiro_role")
@Data
public class ShiroRole implements java.io.Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String roleName;
private Date createTime;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "shiro_role_function", joinColumns = {@JoinColumn(name = "role_id")}, inverseJoinColumns = {
@JoinColumn(name = "function_id")})
private List<Function> functionList;// 一个角色具有多个权限
// @ManyToMany(fetch = FetchType.EAGER)
// @JoinTable(name = "shiro_user_role", joinColumns = {@JoinColumn(name = "role_id")}, inverseJoinColumns = {
// @JoinColumn(name = "user_id")})
// private List<ShiroUser> userList;// 一个角色对应多个用户
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
// public List<ShiroRoleFunction> getPermissionList() {
// return permissionList;
// }
//
// public void setPermissionList(List<ShiroRoleFunction> permissionList) {
// this.permissionList = permissionList;
// }
// public List<ShiroUser> getUserList() {
// return userList;
// }
//
// public void setUserList(List<ShiroUser> userList) {
// this.userList = userList;
// }
// 省略 get set 方法
//
@Transient
public List<String> getPermissionsName() {
List<String> list = new ArrayList<String>();
List<Function> perlist = getFunctionList();
for (Function per : perlist) {
list.add(per.getPermissionName());
}
return list;
}
}

View File

@@ -0,0 +1,103 @@
package com.xinwei.shirofunction;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import lombok.Data;
@Entity
@Table(name = "shiro_user")
@Data
public class ShiroUser implements java.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private String password;
private Date createTime;
private String status;//用户状态:0-注册用户未审核1-注册用户已审核 2-锁定
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "shiro_user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {
@JoinColumn(name = "role_id")})
private List<ShiroRole> roleList;// 一个用户具有多个角色
public ShiroUser() {
super();
}
public ShiroUser(String username, String password) {
super();
this.username = username;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<ShiroRole> getRoleList() {
return roleList;
}
public void setRoleList(List<ShiroRole> roleList) {
this.roleList = roleList;
}
@Transient
public Set<String> getRolesName() {
List<ShiroRole> roles = getRoleList();
Set<String> set = new HashSet<String>();
for (ShiroRole role : roles) {
set.add(role.getRoleName());
}
return set;
}
}

View File

@@ -0,0 +1,20 @@
package com.xinwei.shirofunction;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* 给用户添加role时使用。
* @author ouburikou
*
*/
@Slf4j
@Data
public class UserRoleListCheck {
private String username;
private String roleName;
private boolean check=false;
}

View File

@@ -0,0 +1,221 @@
package com.xinwei.utils;
import java.util.BitSet;
public class ArraysUtil {
/**
* Description: 截取byte数组中的一段作为结果返回
* @Version1.0 2011-4-17 上午10:18:39 laojiang created
* @param a byte数组
* @param begin_index 起始下标
* @param len 截取的长度
* @return 新的数组
*/
public static byte[] subset(byte[] a, int begin_index, int len) {
if (a == null)
return null;
if (begin_index < 0 || len <= 0 || begin_index >= a.length || len > a.length - begin_index)
throw new IllegalArgumentException("Wrong arguments: array length:" + a.length + ", begin index:"
+ begin_index + ", subset length:" + len);
byte[] b = new byte[len];
for (int i = 0; i < len; i++) {
b[i] = a[i + begin_index];
}
return b;
}
/**
* Description: 将byte数组的某一部分转化为一个整数
* @Version1.0 2011-4-17 上午10:19:03 laojiang created
* @param b 数组
* @param begin_index 开始下标
* @param len 截取长度
* @return
*/
public static int toInt(byte[] b, int begin_index, int len) {
byte[] a = subset(b, begin_index, len);
int n = 0;
if (a == null || a.length == 0)
return n;
for (int i = 0; i < a.length; i++) {
n += ((a[i] & 0xff) << ((a.length - i - 1) * 8));
}
return n;
}
/**
* Description: 将一个byte追加到另一个byte数组末尾
* @Version1.0 2011-4-17 上午10:19:28 laojiang created
* @param b1
* @param b2
* @return
*/
public static byte[] concat(byte[] b1, byte b2) {
return concat(b1, new byte[] { b2 });
}
/**
* Description: 将两个byte数组连接在一起并返回
* @Version1.0 2011-4-17 上午10:19:36 laojiang created
* @param b1
* @param b2
* @return
*/
public static byte[] concat(byte[] b1, byte[] b2) {
if (b1 == null)
return b2;
if (b2 == null)
return b1;
byte[] b = new byte[b1.length + b2.length];
for (int i = 0; i < b1.length; i++) {
b[i] = b1[i];
}
for (int j = 0; j < b2.length; j++) {
b[b1.length + j] = b2[j];
}
return b;
}
//把一个20位长的字符串转成Long类型值
public static Long stringToLong(String value) {
if (value == null || "".equals(value)) {
return 0L;
}
return Long.parseLong(value);
}
/**
* 把一个Long类型的值转成一个20位的字符串。位数不够时前面补0
* @param value
* @return
*/
public static String longToString(Long value) {
if (value == null) {
return "00000000000000000000";
}
return String.format("%020d", value);
}
/**
* Description: 将整数转为byte数组
* @Version1.0 2011-4-17 上午10:20:03 laojiang created
* @param num
* @param len
* @return
*/
public static byte[] int2bytes(int num, int len) {
byte[] b = new byte[len];
for (int i = 0; i < len; i++) {
b[i] = (byte) (num >>> ((len - 1 - i) * 8));
}
return b;
}
/**
* Description: 将long转为byte数组
* @Version1.0 2011-9-16 下午14:33:49 tang created
* @param num
* @param len
* @return
*/
public static byte[] longToByte(long num, int len) {
long temp = num;
byte[] b = new byte[len];
for (int i = b.length - 1; i >= 0; i--) {
b[i] = new Long(temp & 0xff).byteValue();// 将最低位保存在最低位
temp = temp >> 8; // 向右移8位
}
return b;
}
public static long unsigned4BytesToInt(byte[] buf, int pos) {
int firstByte = 0;
int secondByte = 0;
int thirdByte = 0;
int fourthByte = 0;
int index = pos;
firstByte = (0x000000FF & ((int) buf[index]));
secondByte = (0x000000FF & ((int) buf[index + 1]));
thirdByte = (0x000000FF & ((int) buf[index + 2]));
fourthByte = (0x000000FF & ((int) buf[index + 3]));
index = index + 4;
return ((long) (firstByte << 24 | secondByte << 16 | thirdByte << 8 | fourthByte)) & 0xFFFFFFFFL;
}
public static long bytes2long(byte[] b) {
int mask = 0xff;
int temp = 0;
int res = 0;
for (int i = 0; i < 8; i++) {
res <<= 8;
temp = b[i] & mask;
res |= temp;
}
return res;
}
/**
* Description: byte数组转换成4字节的long型
* @Version1.0 2011-9-16 下午14:33:49 tang created
* @param num
* @param len
* @return
*/
public static long bytes2LongHandle(byte[] bytes) {
BitSet bs0 = Byte2BitSet(bytes[0]);
//System.out.println(bitset2Int(bs0));
BitSet bs1 = Byte2BitSet(bytes[1]);
//System.out.println(bitset2Int(bs1));
BitSet bs2 = Byte2BitSet(bytes[2]);
//System.out.println(bitset2Int(bs2));
BitSet bs3 = Byte2BitSet(bytes[3]);
//System.out.println(bitset2Int(bs3));
long result = bitset2Int(bs0) * ((long) 256) * 256 * 256 + bitset2Int(bs1) * 256 * 256 + bitset2Int(bs2) * 256
+ bitset2Int(bs3);
return result;
}
public static BitSet Byte2BitSet(byte bytes) {
BitSet bits = new BitSet(8);
for (int i = 0; i < 8; i++) {
if ((bytes & (1 << i)) > 0) {
bits.set(i);
}
}
return bits;
}
public static int bitset2Int(BitSet bs) {
int intValue = 0;
for (int j = 0; j < 32; j++)
if (bs.get(j))
intValue |= 1 << j;
return intValue;
}
/**
* 高字节数组到short的转换
* @param b byte[]
* @return short
*/
public static short hBytesToShort(byte[] b) {
int s = 0;
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
s = s * 256;
if (b[1] >= 0) {
s = s + b[1];
} else {
s = s + 256 + b[1];
}
short result = (short) s;
return result;
}
}

View File

@@ -0,0 +1,192 @@
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.xinwei.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
/**
* Collections工具集.
*
* 在JDK的Collections和Guava的Collections2后, 命名为Collections3.
*
* 函数主要由两部分组成一是自反射提取元素的功能二是源自Apache Commons Collection, 争取不用在项目里引入它。
*
* @author calvin
*/
public class Collections3 {
/**
* 提取集合中的对象的两个属性(通过Getter函数), 组合成Map.
*
* @param collection 来源集合.
* @param keyPropertyName 要提取为Map中的Key值的属性名.
* @param valuePropertyName 要提取为Map中的Value值的属性名.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Map extractToMap(final Collection collection, final String keyPropertyName,
final String valuePropertyName) {
Map map = new HashMap(collection.size());
try {
for (Object obj : collection) {
map.put(PropertyUtils.getProperty(obj, keyPropertyName),
PropertyUtils.getProperty(obj, valuePropertyName));
}
} catch (Exception e) {
throw Reflections.convertReflectionExceptionToUnchecked(e);
}
return map;
}
/**
* 提取集合中的对象的一个属性(通过Getter函数), 组合成List.
*
* @param collection 来源集合.
* @param propertyName 要提取的属性名.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static List extractToList(final Collection collection, final String propertyName) {
List list = new ArrayList(collection.size());
try {
for (Object obj : collection) {
list.add(PropertyUtils.getProperty(obj, propertyName));
}
} catch (Exception e) {
throw Reflections.convertReflectionExceptionToUnchecked(e);
}
return list;
}
/**
* 提取集合中的对象的一个属性(通过Getter函数), 组合成由分割符分隔的字符串.
*
* @param collection 来源集合.
* @param propertyName 要提取的属性名.
* @param separator 分隔符.
*/
@SuppressWarnings("rawtypes")
public static String extractToString(final Collection collection, final String propertyName, final String separator) {
List list = extractToList(collection, propertyName);
return StringUtils.join(list, separator);
}
/**
* 转换Collection所有元素(通过toString())为String, 中间以 separator分隔。
*/
@SuppressWarnings("rawtypes")
public static String convertToString(final Collection collection, final String separator) {
return StringUtils.join(collection, separator);
}
/**
* 转换Collection所有元素(通过toString())为String, 每个元素的前面加入prefix后面加入postfix如<div>mymessage</div>。
*/
@SuppressWarnings("rawtypes")
public static String convertToString(final Collection collection, final String prefix, final String postfix) {
StringBuilder builder = new StringBuilder();
for (Object o : collection) {
builder.append(prefix).append(o).append(postfix);
}
return builder.toString();
}
/**
* 判断是否为空.
*/
@SuppressWarnings("rawtypes")
public static boolean isEmpty(Collection collection) {
return (collection == null || collection.isEmpty());
}
/**
* 判断是否为空.
*/
@SuppressWarnings("rawtypes")
public static boolean isNotEmpty(Collection collection) {
return (collection != null && !(collection.isEmpty()));
}
/**
* 取得Collection的第一个元素如果collection为空返回null.
*/
public static <T> T getFirst(Collection<T> collection) {
if (isEmpty(collection)) {
return null;
}
return collection.iterator().next();
}
/**
* 获取Collection的最后一个元素 如果collection为空返回null.
*/
public static <T> T getLast(Collection<T> collection) {
if (isEmpty(collection)) {
return null;
}
// 当类型为List时直接取得最后一个元素 。
if (collection instanceof List) {
List<T> list = (List<T>) collection;
return list.get(list.size() - 1);
}
// 其他类型通过iterator滚动到最后一个元素.
Iterator<T> iterator = collection.iterator();
while (true) {
T current = iterator.next();
if (!iterator.hasNext()) {
return current;
}
}
}
/**
* 返回a+b的新List.
*/
public static <T> List<T> union(final Collection<T> a, final Collection<T> b) {
List<T> result = new ArrayList<T>(a);
result.addAll(b);
return result;
}
/**
* 返回a-b的新List.
*/
public static <T> List<T> subtract(final Collection<T> a, final Collection<T> b) {
List<T> list = new ArrayList<T>(a);
for (T element : b) {
list.remove(element);
}
return list;
}
/**
* 返回a与b的交集的新List.
*/
public static <T> List<T> intersection(Collection<T> a, Collection<T> b) {
List<T> list = new ArrayList<T>();
for (T element : a) {
if (b.contains(element)) {
list.add(element);
}
}
return list;
}
}

View File

@@ -0,0 +1,97 @@
package com.xinwei.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Constants {
/**
* 企业用户需要审核才能登陆,非企业用户默认审核成功
*/
public static String userStatus_0="0";//注册用户未审核
public static String userStatus_1="1";//注册用户已审核
public static String userStatus_2="2";//注册用户被锁定
public static String initPassword="111111";// 管理员在后台添加用户初始密码 111111
/*****************************************shiro redis 管理设置 start*********************************************************/
/**
* redis cache 前缀
*/
public final static String REDIS_SHIRO_CACHE = "shiro-cache:";
/**
* redis session 前缀
*/
public final static String REDIS_SHIRO_SESSION = "shiro-session:";
/*****************************************shiro redis 管理设置 end*********************************************************/
/*****************************************报表导出 start*********************************************************/
public static List<String> list1 =new ArrayList<String>();
public static List<String> list2 =new ArrayList<String>();
public static Map<String, List> map=new HashMap<String, List>();
public static Map<String, String> mapValue=new HashMap<String, String>();
static{
list1.add("与工业控制系统网络相连的网络");
list1.add("连接方式");
list1.add("连接时间");
list1.add("连接后身份认证方式");
list1.add("连接管理制度");
list1.add("合法系统间互联的识别和认证技术措施");
list2.add("移动存储介质使用管理制度");
list2.add("系统网络和公共网之间交叉使用移动存储介质");
list2.add("工业控制系统主机的存储介质使用情况检查");
list2.add("移动存储介质自动播放功能");
list2.add("工业控制系统与其他系统之间专用的安全信息交换途径");
list2.add("移动存储介质销毁处置流程");
map.put("工业控制系统网络与公共网络的连接管理",list1);
map.put("存储介质使用管理",list2);
mapValue.put("与工业控制系统网络相连的网络", "内部局域网-互联网-企业管理网-其他网络-无连接");
mapValue.put("连接方式","直接相连-采取隔离措施后连接-防火墙");
mapValue.put("连接时间","始终连接-有需要时连接-无连接");
mapValue.put("连接后身份认证方式","口令-数字认证技术-无认证");
mapValue.put("连接管理制度","审批备案-定期检查-风险评估-隔离措施有效性验证-无");
mapValue.put("合法系统间互联的识别和认证技术措施","有-无");
mapValue.put("移动存储介质使用管理制度","有-无");
mapValue.put("系统网络和公共网之间交叉使用移动存储介质","禁止-未禁止-未要求");
mapValue.put("工业控制系统主机的存储介质使用情况检查","定期-不定期-不检查");
mapValue.put("移动存储介质自动播放功能","明文禁止-未禁止-未要求");
mapValue.put("工业控制系统与其他系统之间专用的安全信息交换途径","有-无");
mapValue.put("移动存储介质销毁处置流程","有-无");
}
/*****************************************报表导出 end*********************************************************/
}

View File

@@ -0,0 +1,76 @@
package com.xinwei.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang3.StringUtils;
public class ConvertUtils {
static {
registerDateConverter();
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成List.
*
* @param collection 来源集合.
* @param propertyName 要提取的属性名.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static List convertElementPropertyToList(final Collection collection, final String propertyName) {
List list = new ArrayList();
try {
for (Object obj : collection) {
list.add(PropertyUtils.getProperty(obj, propertyName));
}
} catch (Exception e) {
throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
}
return list;
}
/**
* 提取集合中的对象的属性(通过getter函数), 组合成由分割符分隔的字符串.
*
* @param collection 来源集合.
* @param propertyName 要提取的属性名.
* @param separator 分隔符.
*/
@SuppressWarnings("rawtypes")
public static String convertElementPropertyToString(final Collection collection, final String propertyName,
final String separator) {
List list = convertElementPropertyToList(collection, propertyName);
return StringUtils.join(list, separator);
}
/**
* 转换字符串到相应类型.
*
* @param value 待转换的字符串.
* @param toType 转换目标类型.
*/
public static Object convertStringToObject(String value, Class<?> toType) {
try {
return org.apache.commons.beanutils.ConvertUtils.convert(value, toType);
} catch (Exception e) {
throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
}
}
/**
* 定义日期Converter的格式: yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
*/
private static void registerDateConverter() {
DateConverter dc = new DateConverter();
dc.setUseLocaleFormat(true);
dc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" });
org.apache.commons.beanutils.ConvertUtils.register(dc, Date.class);
}
}

View File

@@ -0,0 +1,118 @@
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.xinwei.utils;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import org.apache.commons.lang3.Validate;
/**
* 支持SHA-1/MD5消息摘要的工具类.
*
* 返回ByteSource可进一步被编码为Hex, Base64或UrlSafeBase64
*
* @author calvin
*/
public class Digests {
private static final String SHA1 = "SHA-1";
private static final String MD5 = "MD5";
private static SecureRandom random = new SecureRandom();
/**
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input) {
return digest(input, SHA1, null, 1);
}
public static byte[] sha1(byte[] input, byte[] salt) {
return digest(input, SHA1, salt, 1);
}
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
return digest(input, SHA1, salt, iterations);
}
public static byte[] md5(byte[] input,byte[] salt, int iterations){
return digest(input, MD5, salt, iterations);
}
/**
* 对字符串进行散列, 支持md5与sha1算法.
*/
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
if (salt != null) {
digest.update(salt);
}
byte[] result = digest.digest(input);
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 生成随机的Byte[]作为salt.
*
* @param numBytes byte数组的大小
*/
public static byte[] generateSalt(int numBytes) {
Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
byte[] bytes = new byte[numBytes];
random.nextBytes(bytes);
return bytes;
}
/**
* 对文件进行md5散列.
*/
public static byte[] md5(InputStream input) throws IOException {
return digest(input, MD5);
}
/**
* 对文件进行sha1散列.
*/
public static byte[] sha1(InputStream input) throws IOException {
return digest(input, SHA1);
}
private static byte[] digest(InputStream input, String algorithm) throws IOException {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
int bufferLength = 8 * 1024;
byte[] buffer = new byte[bufferLength];
int read = input.read(buffer, 0, bufferLength);
while (read > -1) {
messageDigest.update(buffer, 0, read);
read = input.read(buffer, 0, bufferLength);
}
return messageDigest.digest();
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
}

View File

@@ -0,0 +1,179 @@
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.xinwei.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;
/**
* 封装各种格式的编码解码工具类.
*
* 1.Commons-Codec的 hex/base64 编码
* 2.自制的base62 编码
* 3.Commons-Lang的xml/html escape
* 4.JDK提供的URLEncoder
*
* @author calvin
*/
public class Encodes {
private static final String DEFAULT_URL_ENCODING = "UTF-8";
private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
/**
* Hex编码.
*/
public static String encodeHex(byte[] input) {
return Hex.encodeHexString(input);
}
/**
* Hex解码.
*/
public static byte[] decodeHex(String input) {
try {
return Hex.decodeHex(input.toCharArray());
} catch (DecoderException e) {
throw Exceptions.unchecked(e);
}
}
/**
* Base64编码.
*/
public static String encodeBase64(byte[] input) {
return Base64.encodeBase64String(input);
}
/**
* Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
*/
public static String encodeUrlSafeBase64(byte[] input) {
return Base64.encodeBase64URLSafeString(input);
}
/**
* Base64解码.
*/
public static byte[] decodeBase64(String input) {
return Base64.decodeBase64(input);
}
/**
* Base62编码。
*/
public static String encodeBase62(byte[] input) {
char[] chars = new char[input.length];
for (int i = 0; i < input.length; i++) {
chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
}
return new String(chars);
}
/**
* Html 转码.
*/
public static String escapeHtml(String html) {
return StringEscapeUtils.escapeHtml4(html);
}
/**
* Html 解码.
*/
public static String unescapeHtml(String htmlEscaped) {
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
}
/**
* Xml 转码.
*/
public static String escapeXml(String xml) {
return StringEscapeUtils.escapeXml(xml);
}
/**
* Xml 解码.
*/
public static String unescapeXml(String xmlEscaped) {
return StringEscapeUtils.unescapeXml(xmlEscaped);
}
/**
* URL 编码, Encode默认为UTF-8.
*/
public static String urlEncode(String part) {
try {
return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
/**
* URL 解码, Encode默认为UTF-8.
*/
public static String urlDecode(String part) {
try {
return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
public static String md5(String rawPass, Object salt) {
return md5(rawPass, salt, 1);
}
private static String mergePasswordAndSalt(String password, Object salt,
boolean strict) {
if (password == null) {
password = "";
}
if (strict && (salt != null)) {
if ((salt.toString().lastIndexOf("{") != -1)
|| (salt.toString().lastIndexOf("}") != -1)) {
throw new IllegalArgumentException(
"Cannot use { or } in salt.toString()");
}
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt.toString() + "}";
}
}
public static String md5(String rawPass, Object salt, int iterations) {
try {
String saltedPass = mergePasswordAndSalt(rawPass, salt, false);
MessageDigest messageDigest = MessageDigest.getInstance("md5");
byte[] digest = messageDigest.digest(saltedPass.getBytes());
for (int i = 1; i < 1; i++) {
digest = messageDigest.digest(digest);
}
return encodeHex(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.xinwei.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 关于异常的工具类.
*
* @author calvin
*/
public class Exceptions {
/**
* 将CheckedException转换为UncheckedException.
*/
public static RuntimeException unchecked(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new RuntimeException(e);
}
}
/**
* 将ErrorStack转化为String.
*/
public static String getStackTraceAsString(Exception e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* 判断异常是否由某些底层的异常引起.
*/
@SafeVarargs
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
Throwable cause = ex.getCause();
while (cause != null) {
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
if (causeClass.isInstance(cause)) {
return true;
}
}
cause = cause.getCause();
}
return false;
}
}

View File

@@ -0,0 +1,269 @@
package com.xinwei.utils;
public class GFString {
/**
* 在str每个字符之间添加cha
* @param str 准备拆分的字符串
* @param cha 添加的字符
* @return
*/
public static String supplement(String str,char cha){
StringBuilder sb = new StringBuilder(str);
for(int i=0;i<str.length();i++){
sb.insert(i*2, cha);
}
return sb.toString();
}
/**
* Description: 把相临的两个字符对换字符串长度为奇数时最后加“F”
* @Version1.0 2011-4-17 上午10:20:33 laojiang created
* @param src 对换后的字符串
* @return
*/
public static String interChange(String src) {
String result = null;
if (src != null) {
if (src.length() % 2 != 0) {
src += "F";
}
src += "0";
result = "";
for (int i = 0; i < src.length() - 2; i += 2) {
result += src.substring(i + 1, i + 2);
result += src.substring(i, i + 1);
}
}
return result;
}
/**
* Description:
* @Version1.0 2011-4-17 上午10:20:41 laojiang created
* @param gbString
* @return
*/
public static String gb2unicode(String gbString) {
String result = "";
// GB2Uni nn = new GB2Uni();
char[] c;
int value;
if (gbString == null) {
return null;
}
// if (gbString.getBytes().length == gbString.length())
// return gbString;
String temp = null;
c = new char[gbString.length()];
StringBuffer sb = new StringBuffer(gbString);
sb.getChars(0, sb.length(), c, 0);
for (int i = 0; i < c.length; i++) {
value = c[i];
// System.out.println("[" + i + "]:" +value );
// System.out.println("hex:"+Integer.toHexString(value));
temp = Integer.toHexString(value);
result += fill(temp, 4);
//-------------------------------------------------------------------------
}
return result.toUpperCase();
}
public static String fill(String temp, int totalbit) {
String t = temp;
while (t.length() < totalbit) {
t = "0" + t;
}
return t;
}
/**
* Description: 对7-BIT编码进行解码
* @Version1.0 2011-4-17 上午10:20:52 laojiang created
* @param src 十六进制的字符串,且为偶数个
* @return 源字符串
*/
public static String decode7bit(String src) {
String result = null;
int[] b;
String temp = null;
byte srcAscii;
byte left = 0;
if (src != null && src.length() % 2 == 0) {
result = "";
b = new int[src.length() / 2];
temp = src + "0";
for (int i = 0, j = 0, k = 0; i < temp.length() - 2; i += 2, j++) {
b[j] = Integer.parseInt(temp.substring(i, i + 2), 16);
k = j % 7;
srcAscii = (byte) (((b[j] << k) & 0x7F) | left);
result += (char) srcAscii;
left = (byte) (b[j] >>> (7 - k));
if (k == 6) {
result += (char) left;
left = 0;
}
if (j == src.length() / 2) {
result += (char) left;
}
}
}
return result;
}
public static String decode8bit(String src) {
String temp = src;
String result = "";
for (int i = 0; i < src.length() - 2; i += 2) {
result += (char) Integer.parseInt(temp.substring(i, i + 2), 16);
}
return result;
}
/**
* Description: 把UNICODE编码的字符串转化成汉字编码的字符串
* @Version1.0 2011-4-17 上午10:21:17 laojiang created
* @param hexString 转化后的字符串
* @return
*/
public static String unicode2gb(String hexString) {
StringBuffer sb = new StringBuffer();
if (hexString == null) {
return null;
}
for (int i = 0; i + 4 <= hexString.length(); i = i + 4) {
try {
int j = Integer.parseInt(hexString.substring(i, i + 4), 16);
sb.append((char) j);
} catch (NumberFormatException e) {
return hexString;
}
}
return sb.toString();
}
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
public static String byte2hex(byte b) {
String hs = "";
String stmp = "";
{
stmp = (java.lang.Integer.toHexString(b & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
// if (n<b.length-1) hs=hs+":";
}
return hs.toUpperCase();
}
/**
* Description: 将16进制字符串转换成字节码
* @Version1.0 2011-4-17 上午10:21:40 laojiang created
* @param hex
* @return
*/
public static byte[] hex2byte(String hex) {
byte[] bts = new byte[hex.length() / 2];
for (int i = 0; i < bts.length; i++) {
bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return bts;
}
// TODO:temp
public static String encode7bit(String src) {
String result = null;
String hex = null;
byte value;
if (src != null && src.length() == src.getBytes().length && src.length() == 1) {
result = GFString.byte2hex(src.getBytes());
} else if (src != null && src.length() == src.getBytes().length) {
result = "";
byte left = 0;
byte[] b = src.getBytes();
for (int i = 0, j = 0; i < b.length; i++) {
j = i & 7;
if (j == 0) {
left = b[i];
} else {
value = (byte) ((b[i] << (8 - j)) | left);
left = (byte) (b[i] >> j);
hex = GFString.byte2hex(value);
result += hex;
if (i == b.length - 1) {
result += GFString.byte2hex(left);
}
}
}
result = result.toUpperCase();
}
return result;
}
/**
* Description: 获得字符串的BCD码
* @Version1.0 2011-4-17 上午10:21:54 laojiang created
* @param asc
* @return
*/
public static byte[] str2Bcd(String asc) {
int len = asc.length();
int mod = len % 2;
if (mod != 0) {
asc = "0" + asc;
len = asc.length();
}
byte abt[] = new byte[len];
if (len >= 2) {
len = len / 2;
}
byte bbt[] = new byte[len];
abt = asc.getBytes();
int j, k;
for (int p = 0; p < asc.length() / 2; p++) {
if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
j = abt[2 * p] - '0';
} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
j = abt[2 * p] - 'a' + 0x0a;
} else {
j = abt[2 * p] - 'A' + 0x0a;
}
if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
k = abt[2 * p + 1] - '0';
} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
k = abt[2 * p + 1] - 'a' + 0x0a;
} else {
k = abt[2 * p + 1] - 'A' + 0x0a;
}
int a = (j << 4) + k;
byte b = (byte) a;
bbt[p] = b;
}
return bbt;
}
}

View File

@@ -0,0 +1,66 @@
package com.xinwei.utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Hibernate;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQL5InnoDBDialect;
import org.hibernate.dialect.Oracle10gDialect;
public class Hibernates {
public static final String DATETIME_TYPE = "org.jadira.usertype.dateandtime.joda.PersistentDateTime";
/**
* Initialize the lazy property value.
*
* eg.
* Hibernates.initLazyProperty(user.getGroups());
*/
public static void initLazyProperty(Object proxyedPropertyValue) {
Hibernate.initialize(proxyedPropertyValue);
}
/**
* 从DataSoure中取出connection, 根据connection的metadata中的jdbcUrl判断Dialect类型.
* 仅支持Oracle, H2, MySql如需更多数据库类型请仿照此类自行编写。
*/
public static String getDialect(DataSource dataSource) {
String jdbcUrl = getJdbcUrlFromDataSource(dataSource);
// 根据jdbc url判断dialect
if (StringUtils.contains(jdbcUrl, ":h2:")) {
return H2Dialect.class.getName();
} else if (StringUtils.contains(jdbcUrl, ":mysql:")) {
return MySQL5InnoDBDialect.class.getName();
} else if (StringUtils.contains(jdbcUrl, ":oracle:")) {
return Oracle10gDialect.class.getName();
} else {
throw new IllegalArgumentException("Unknown Database of " + jdbcUrl);
}
}
private static String getJdbcUrlFromDataSource(DataSource dataSource) {
Connection connection = null;
try {
connection = dataSource.getConnection();
if (connection == null) {
throw new IllegalStateException("Connection returned by DataSource [" + dataSource + "] was null");
}
return connection.getMetaData().getURL();
} catch (SQLException e) {
throw new RuntimeException("Could not get database url", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
package com.xinwei.utils;
import java.lang.reflect.Field;
public class ObjectToObject {
public static <T> void mergeObject(T origin, T destination) {
if (origin == null || destination == null)
return;
if (!origin.getClass().equals(destination.getClass()))
return;
Field[] fields = origin.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
fields[i].setAccessible(true);
Object value = fields[i].get(origin);
if (null != value) {
fields[i].set(destination, value);
}
fields[i].setAccessible(false);
} catch (Exception e) {
}
}
}
}

View File

@@ -0,0 +1,211 @@
package com.xinwei.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
/**
* 反射工具类.
*
* 提供访问私有变量,获取泛型类型Class, 提取集合中元素的属性, 转换字符串到对象等Util函数.
*/
public class ReflectionUtils {
private static Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);
/**
* 调用Getter方法.
*/
public static Object invokeGetterMethod(Object obj, String propertyName) {
String getterMethodName = "get" + StringUtils.capitalize(propertyName);
return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {});
}
/**
* 调用Setter方法.使用value的Class来查找Setter方法.
*/
public static void invokeSetterMethod(Object obj, String propertyName, Object value) {
invokeSetterMethod(obj, propertyName, value, null);
}
/**
* 调用Setter方法.
*
* @param propertyType 用于查找Setter方法,为空时使用value的Class替代.
*/
public static void invokeSetterMethod(Object obj, String propertyName, Object value, Class<?> propertyType) {
Class<?> type = propertyType != null ? propertyType : value.getClass();
String setterMethodName = "set" + StringUtils.capitalize(propertyName);
invokeMethod(obj, setterMethodName, new Class[] { type }, new Object[] { value });
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
public static Object getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
Object result = null;
try {
result = field.get(obj);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
*
* 如向上转型到Object仍无法找到, 返回null.
*/
public static Field getAccessibleField(final Object obj, final String fieldName) {
Assert.notNull(obj, "object不能为空");
Assert.hasText(fieldName, "fieldName");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {//NOSONAR
// Field不在当前类定义,继续向上转型
}
}
return null;
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况.
*/
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
Assert.notNull(obj, "object不能为空");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Method method = superClass.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException e) {//NOSONAR
// Method不在当前类定义,继续向上转型
}
}
return null;
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
* eg.
* public UserDao extends HibernateDao<User>
*
* @param clazz The class to introspect
* @return the first generic declaration, or Object.class if cannot be determined
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
*
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz clazz The class to introspect
* @param index the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be determined
*/
@SuppressWarnings("rawtypes")
public static Class getSuperClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
/**
* 将反射时的checked exception转换为unchecked exception.
*/
public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException("Reflection Exception.", e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException("Reflection Exception.", ((InvocationTargetException) e).getTargetException());
} else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
}

View File

@@ -0,0 +1,290 @@
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.xinwei.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
/**
* 反射工具类.
*
* 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
*
* @author calvin
*/
public class Reflections {
private static final String SETTER_PREFIX = "set";
private static final String GETTER_PREFIX = "get";
private static final String CGLIB_CLASS_SEPARATOR = "$$";
private static Logger logger = LoggerFactory.getLogger(Reflections.class);
/**
* 调用Getter方法.
*/
public static Object invokeGetter(Object obj, String propertyName) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(propertyName);
return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {});
}
/**
* 调用Setter方法, 仅匹配方法名。
*/
public static void invokeSetter(Object obj, String propertyName, Object value) {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(propertyName);
invokeMethodByName(obj, setterMethodName, new Object[] { value });
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
public static Object getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
Object result = null;
try {
result = field.get(obj);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
}
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常:{}", e.getMessage());
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况否则应使用getAccessibleMethod()函数获得Method后反复调用.
* 同时匹配方法名+参数类型,
*/
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符
* 用于一次性调用的情况否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
*/
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
Method method = getAccessibleMethodByName(obj, methodName);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
}
try {
return method.invoke(obj, args);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
*
* 如向上转型到Object仍无法找到, 返回null.
*/
public static Field getAccessibleField(final Object obj, final String fieldName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(fieldName, "fieldName can't be blank");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
makeAccessible(field);
return field;
} catch (NoSuchFieldException e) {//NOSONAR
// Field不在当前类定义,继续向上转型
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 匹配函数名+参数类型。
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
try {
Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
makeAccessible(method);
return method;
} catch (NoSuchMethodException e) {
// Method不在当前类定义,继续向上转型
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 只匹配函数名。
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
Method[] methods = searchType.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
makeAccessible(method);
return method;
}
}
}
return null;
}
/**
* 改变private/protected的方法为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
/**
* 改变private/protected的成员变量为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。
*/
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
* 如无法找到, 返回Object.class.
* eg.
* public UserDao extends HibernateDao<User>
*
* @param clazz The class to introspect
* @return the first generic declaration, or Object.class if cannot be determined
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> Class<T> getClassGenricType(final Class clazz) {
return getClassGenricType(clazz, 0);
}
/**
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
* 如无法找到, 返回Object.class.
*
* 如public UserDao extends HibernateDao<User,Long>
*
* @param clazz clazz The class to introspect
* @param index the Index of the generic ddeclaration,start from 0.
* @return the index generic declaration, or Object.class if cannot be determined
*/
@SuppressWarnings("rawtypes")
public static Class getClassGenricType(final Class clazz, final int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ params.length);
return Object.class;
}
if (!(params[index] instanceof Class)) {
logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
return Object.class;
}
return (Class) params[index];
}
@SuppressWarnings("rawtypes")
public static Class<?> getUserClass(Object instance) {
Assert.notNull(instance, "Instance must not be null");
Class clazz = instance.getClass();
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && !Object.class.equals(superClass)) {
return superClass;
}
}
return clazz;
}
/**
* 将反射时的checked exception转换为unchecked exception.
*/
public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|| e instanceof NoSuchMethodException) {
return new IllegalArgumentException(e);
} else if (e instanceof InvocationTargetException) {
return new RuntimeException(((InvocationTargetException) e).getTargetException());
} else if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new RuntimeException("Unexpected Checked Exception.", e);
}
}

View File

@@ -0,0 +1,44 @@
package com.xinwei.utils;
import lombok.Data;
@Data
public class ResponseJson {
public String msg;
public String url;
public String returnStr;
public boolean success=true;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getReturnStr() {
return returnStr;
}
public void setReturnStr(String returnStr) {
this.returnStr = returnStr;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
}

View File

@@ -0,0 +1,75 @@
package com.xinwei.utils;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Maps;
public class SearchFilter {
public enum Operator {
NEQ, EQ, LIKE, GT, LT, GTE, LTE, ISNULL, ISNOTNULL
}
/** 属性数据类型. */
public enum PropertyType {
S(String.class), I(Integer.class), L(Long.class), N(Double.class), D(Date.class), B(Boolean.class);
private Class<?> clazz;
private PropertyType(Class<?> clazz) {
this.clazz = clazz;
}
public Class<?> getValue() {
return clazz;
}
}
public String fieldName;
public Object value;
public Operator operator;
public SearchFilter(String fieldName, Operator operator, Object value) {
this.fieldName = fieldName;
this.value = value;
this.operator = operator;
}
/**
* searchParams中key的格式为OPERATOR_FIELDNAME
*/
@SuppressWarnings("rawtypes")
public static Map<String, SearchFilter> parse(Map<String, Object> searchParams) {
Map<String, SearchFilter> filters = Maps.newHashMap();
for (Entry<String, Object> entry : searchParams.entrySet()) {
// 过滤掉空值
String key = entry.getKey();
Object value = entry.getValue();
if (StringUtils.isBlank((String) value)) {
continue;
}
// 拆分operator与filedAttribute
String[] names = StringUtils.split(key, "_");
if (names.length != 2) {
throw new IllegalArgumentException(key + " is not a valid search filter name");
}
String filedName = names[1];
String firstPart = names[0];
String matchTypeCode = StringUtils.substring(firstPart, 0, firstPart.length() - 1);
String propertyTypeCode = StringUtils.substring(firstPart, firstPart.length() - 1, firstPart.length());
Operator operator = Operator.valueOf(matchTypeCode);
Class propertyClass = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue();
Object obj = ConvertUtils.convertStringToObject(value.toString(), propertyClass);
// 创建searchFilter
SearchFilter filter = new SearchFilter(filedName, operator, obj);
filters.put(key, filter);
}
return filters;
}
}

View File

@@ -0,0 +1,91 @@
package com.xinwei.utils;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
public class StringUtil {
/**
* Description: 将16进制字节数组转换为字符 每个字节第一位为0 如08转为8
* @Version1.0 2012-5-25 下午06:19:53 yangll created
* @param bytes
* @return
*/
public static String toHexStringNum(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length);
String sTemp;
for (int i = 0; i < bytes.length; i++) {
sTemp = Integer.toHexString(0xFF & bytes[i]);
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
/**
* Description: 将16进制字节数组转换为字符 每个字节第一位不为0 如1A转为1A
* @Version1.0 2011-4-17 上午10:22:14 laojiang created
* @param bytes
* @return
*/
public static String toHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length);
String sTemp;
for (int i = 0; i < bytes.length; i++) {
sTemp = Integer.toHexString(0xFF & bytes[i]);
if (sTemp.length() < 2) {
sb.append(0);
}
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
/**
* Description: 将字节转换成16进制字符
* @Version1.0 2011-4-17 上午10:22:25 laojiang created
* @param b
* @return
*/
public static String byteToString(byte b) {
byte high, low;
byte maskHigh = (byte) 0xf0;
byte maskLow = 0x0f;
high = (byte) ((b & maskHigh) >> 4);
low = (byte) (b & maskLow);
StringBuffer buf = new StringBuffer();
buf.append(findHex(high));
buf.append(findHex(low));
return buf.toString();
}
private static char findHex(byte b) {
int t = new Byte(b).intValue();
t = t < 0 ? t + 16 : t;
if ((0 <= t) && (t <= 9)) {
return (char) (t + '0');
}
return (char) (t - 10 + 'A');
}
/**
* Description: 将字节数组转换成字符串
* @Version1.0 2011-9-22 上午11:01:56 tang created
* @param bytes
* @return
*/
public static char[] v2BytesToChars(byte[] bytes) {
Charset cs = Charset.forName("UTF-8");
ByteBuffer bb = ByteBuffer.allocate(bytes.length);
bb.put(bytes);
bb.flip();
CharBuffer cb = cs.decode(bb);
return cb.array();
}
}

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shiro-springboot-demo</artifactId>
<groupId>demo.xinwin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-shiro-service</artifactId>
<dependencies>
<dependency>
<groupId>demo.xinwin</groupId>
<artifactId>demo-shiro-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,12 @@
package com.xinwei.dao;
import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
@NoRepositoryBean
public interface BaseDao<T, pk extends Serializable> extends PagingAndSortingRepository<T, Serializable>,
JpaSpecificationExecutor<T> {
}

View File

@@ -0,0 +1,24 @@
package com.xinwei.dao;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Service;
import com.xinwei.shirofunction.Function;
@Transactional
@Service
public interface FunctionDao extends BaseDao<Function, Long> {
@Query("from Function")
public List<Function> findList();
public Function findByPermissionName(String permissionName);
public Function findByPid(Integer pid);
@Query("from Function where pid=?")
public List<Function> findListByPid(Integer pid);
}

View File

@@ -0,0 +1,23 @@
package com.xinwei.dao;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Service;
import com.xinwei.shirofunction.ShiroRole;
@Transactional
@Service
public interface ShiroRoleDao extends BaseDao<ShiroRole, Long> {
@Query("from ShiroRole")
public List<ShiroRole> findRoleList();
public ShiroRole findByRoleName(String roleName);
}

View File

@@ -0,0 +1,22 @@
package com.xinwei.dao;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import com.xinwei.shirofunction.ShiroUser;
@Service
public interface ShiroUserDao extends BaseDao<ShiroUser, Long> {
public ShiroUser findByUsername(String userName);
@Query(value = "select j from ShiroUser j where j.username = :username ")
public ShiroUser findByUsernameForUpdate(@Param("username") String username);
// 动态sql分页查询
Page<ShiroUser> findAll(Specification<ShiroUser> spec, Pageable pageable);
}

View File

@@ -0,0 +1,117 @@
/**
*
*/
package com.xinwei.service.impl;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import com.xinwei.common.page.DynamicSpecifications;
import com.xinwei.dao.BaseDao;
import com.xinwei.service.EntityService;
import com.xinwei.utils.ReflectionUtils;
import com.xinwei.utils.SearchFilter;
/**
*
* 所有业务查询实现类的基类
*/
public abstract class EntityServiceImpl<T, PK extends Serializable, EntityDao extends BaseDao<T, PK>> implements
EntityService<T, PK> {
protected Class<T> entityClass;
protected EntityDao entityDao;
@Override
public T get(PK id) {
return entityDao.findOne(id);
}
@Override
public void delete(PK id) {
entityDao.delete(id);
}
public void delete(T entity){
entityDao.delete(entity);
}
@Override
public void save(T t) {
entityDao.save(t);
}
@Override
public Iterable<T> getAll() {
return entityDao.findAll();
}
public EntityServiceImpl() {
this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
}
/**
* 创建分页请求.
*/
protected PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
Sort sort = null;
if ("auto".equals(sortType)) {
sort = new Sort(Direction.ASC, "id");
} else if (sortType != null && !"".equals(sortType) && !sortType.contains("_ASC")) {
sort = new Sort(Direction.DESC, sortType);
} else if(null != sortType && sortType.contains("_ASC")) {
sort = new Sort(Direction.ASC, sortType.split("_ASC")[0]);
}
return new PageRequest(pageNumber - 1, pagzSize, sort);
}
/**
* 创建动态查询条件组合.
*/
protected Specification<T> buildSpecification(Map<String, Object> searchParams) {
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), entityClass);
return spec;
}
@Override
public Page<T> search(Map<String, Object> searchParams, int pageNumber, int pageSize, String sortType) {
PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
if (searchParams!=null) {
Specification<T> spec = buildSpecification(searchParams);
return entityDao.findAll(spec, pageRequest);
}
return entityDao.findAll(pageRequest);
}
@Override
public List<T> findAll(Map<String, Object> searchParams, Sort sort) {
return entityDao.findAll(buildSpecification(searchParams), sort);
}
@Override
public List<T> findAll(Map<String, Object> searchParams) {
return entityDao.findAll(buildSpecification(searchParams));
}
public abstract void setEntityDao(EntityDao entityDao);
@Override
public void delete(Iterable<T> entities) {
entityDao.delete(entities);
}
}

View File

@@ -0,0 +1,101 @@
package com.xinwei.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.common.page.SpecificationUtil;
import com.xinwei.dao.FunctionDao;
import com.xinwei.shirofunction.Function;
import com.xinwei.shirofunction.FunctionService;
@Service
public class FunctionServiceImpl extends EntityServiceImpl<Function, Long, FunctionDao> implements FunctionService {
@Override
public List<Function> findList(){
return entityDao.findList();
}
@Override
public Function findById(Integer id){
return entityDao.findOne(id);
}
@Override
public Function findByPermissionName(String permissionName){
return entityDao.findByPermissionName(permissionName);
}
@Override
public Function findByPid(Integer pid){
return entityDao.findByPid(pid);
}
@Override
public List<Function> findListByPid(Integer pid){
return entityDao.findListByPid(pid);
}
@Override
public PaginationResult<Function> findAllByPage(Pagination<Function> pagination){
SpecificationUtil<Function> specificationUtil = new SpecificationUtil<Function>();
Map<String, Object> searchParams = new HashMap<String, Object>();
List<String> properties = new ArrayList<String>();
properties.add("id");
Sort sort = new Sort(Direction.DESC, properties);
sort= pagination.dataTableOrder(pagination,sort,properties);
String id = pagination.getExtra_search();
searchParams.put("EQS_id", id);
Specification<Function> specification = specificationUtil.buildSpecification(searchParams,"and");
// int page= pagination.getStart()/pagination.getPageSize();
PageRequest PageRequest = null;//new PageRequest( page,pagination.getPageSize(), sort);
Page<Function> list = entityDao.findAll(specification, PageRequest);
PaginationResult<Function> pa=new PaginationResult();
pa.setData(list.getContent());
pa.setRecordsFiltered(list.getTotalElements());
pa.setRecordsTotal(list.getTotalElements());
pa.setDraw(new Integer(pagination.getDraw()));
return pa;
}
@Override
@Autowired
public void setEntityDao(FunctionDao entityDao) {
this.entityDao = entityDao;
}
}

View File

@@ -0,0 +1,86 @@
package com.xinwei.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.common.page.SpecificationUtil;
import com.xinwei.dao.ShiroRoleDao;
import com.xinwei.service.ShiroRoleService;
import com.xinwei.shirofunction.ShiroRole;
@Service
public class ShiroRoleServiceImpl extends EntityServiceImpl<ShiroRole, Long, ShiroRoleDao> implements ShiroRoleService {
@Override
public List<ShiroRole> findRoleList(){
return entityDao.findRoleList();
}
@Override
public ShiroRole findByRoleName(String rolename){
return entityDao.findByRoleName(rolename);
}
@Override
public ShiroRole findById(Integer id){
return entityDao.findOne(id);
}
@Override
public PaginationResult<ShiroRole> findAllByPage(Pagination<ShiroRole> pagination){
SpecificationUtil<ShiroRole> specificationUtil = new SpecificationUtil<ShiroRole>();
Map<String, Object> searchParams = new HashMap<String, Object>();
List<String> properties = new ArrayList<String>();
properties.add("id");
Sort sort = new Sort(Direction.DESC, properties);
sort= pagination.dataTableOrder(pagination,sort,properties);
Specification<ShiroRole> specification = specificationUtil.buildSpecification(searchParams,"and");
int page= pagination.getStart()/pagination.getPageSize();
PageRequest PageRequest = new PageRequest( page,pagination.getPageSize(), sort);
Page<ShiroRole> list = entityDao.findAll(specification, PageRequest);
PaginationResult<ShiroRole> pa=new PaginationResult();
pa.setData(list.getContent());
pa.setRecordsFiltered(list.getTotalElements());
pa.setRecordsTotal(list.getTotalElements());
pa.setDraw(new Integer(pagination.getDraw()));
return pa;
}
@Override
@Autowired
public void setEntityDao(ShiroRoleDao entityDao) {
this.entityDao = entityDao;
}
}

View File

@@ -0,0 +1,314 @@
package com.xinwei.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.common.page.SpecificationUtil;
import com.xinwei.dao.ShiroUserDao;
import com.xinwei.service.ShiroRoleService;
import com.xinwei.service.ShiroUserService;
import com.xinwei.shirofunction.ShiroRole;
import com.xinwei.shirofunction.ShiroUser;
import com.xinwei.utils.Constants;
import com.xinwei.utils.ResponseJson;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class ShiroUserServiceImpl extends EntityServiceImpl<ShiroUser, Long, ShiroUserDao> implements ShiroUserService {
@Autowired
ShiroRoleService shiroRoleService;
/**
* 管理员修改用户基本信息
*/
@Transactional(rollbackFor=Exception.class)
@Override
public ResponseJson editUser(ShiroUser shiroUser){
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
log.info(shiroUser.toString());
ShiroUser shiroUserTemp = this.findByUsernameForUpdate(shiroUser.getUsername());
this.save(shiroUserTemp);
return responseJson;
}
/**
* 管理员添加用户
*/
@Transactional(rollbackFor=Exception.class)
@Override
public ResponseJson addUser(ShiroUser shiroUser){
ResponseJson responseJson = new ResponseJson();
ShiroUser shiroUserTemp=null;
try {
shiroUserTemp = this.findByUsername(shiroUser.getUsername());
if(shiroUserTemp!=null){
responseJson.setMsg("usernameExist");
return responseJson;
}
String password = new Md5Hash(Constants.initPassword, "www",1024).toBase64();
shiroUser.setPassword(password);
shiroUser.setStatus(Constants.userStatus_0);
shiroUser.setCreateTime(new Date());
this.save(shiroUser);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
responseJson.setMsg("false");
return responseJson;
}
responseJson.setMsg("success");
return responseJson;
}
@Transactional(rollbackFor=Exception.class)
@Override
public ResponseJson checkNameOrEmallExist(ShiroUser shiroUser){
ResponseJson responseJson = new ResponseJson();
log.info(shiroUser.toString());
ShiroRole shiroRoleTemp=null;
ShiroUser shiroUserTemp=null;
try {
shiroUserTemp = this.findByUsername(shiroUser.getUsername());
if(shiroUserTemp!=null){
responseJson.setMsg("false");
return responseJson;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
responseJson.setMsg("false");
return responseJson;
}
responseJson.setMsg("true");
return responseJson;
}
/**
* 删除
*/
@Override
@Transactional(rollbackFor=Exception.class)
public ResponseJson del( String ids) throws Exception{
ResponseJson responseJson = new ResponseJson();
ShiroUser user;
String idsArr[] = ids.split(",");
for (int i = 0; i < idsArr.length; i++) {
user = entityDao.findByUsername(idsArr[i]);
if(user.getUsername().equals("admin")){
responseJson.setMsg("admin");
throw new Exception("admin");
}
entityDao.delete(user);
}
responseJson.setMsg("success");
return responseJson;
}
public ResponseJson editUserRole(String username,String roles){
ResponseJson responseJson= new ResponseJson();
ShiroUser shiroUserTemp = this.findByUsernameForUpdate(username);
String rolesArr[] = roles.split(",");
List<ShiroRole> roleList = new ArrayList<ShiroRole>();
for(int i=0;i<rolesArr.length;i++){
ShiroRole shiroRoleTemp = shiroRoleService.findByRoleName(rolesArr[i]);
roleList.add(shiroRoleTemp);
}
shiroUserTemp.setRoleList(roleList);
this.save(shiroUserTemp);
responseJson.setMsg("success");
responseJson.setSuccess(true);
return responseJson;
}
@Override
public ShiroUser findByUsernameForUpdate(String username){
return entityDao.findByUsernameForUpdate(username);
}
@Override
public ShiroUser findByUsername(String userName) {
return entityDao.findByUsername(userName);
}
@Transactional(rollbackFor=Exception.class)
@Override
public ResponseJson audit(String userNameStr,String status) throws Exception{
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
String userNameArray[]=userNameStr.split(",");
int length = userNameArray.length;
log.info("length===="+length);
for(int i =0;i<length;i++){
String username = userNameArray[i];
log.info("username===="+username);
log.info("status===="+status);
ShiroUser shiroUser = entityDao.findByUsername(username);
if(shiroUser.getRoleList()==null||shiroUser.getRoleList().size()==0){//审核之前必须先给用户赋角色
throw new Exception("roleNotExist");
}else{
shiroUser.setStatus(status);
entityDao.save(shiroUser);
responseJson.setMsg("success");
}
}
return responseJson;
}
@Override
public List<ShiroUser> findList() {
List<ShiroUser> list = (List) entityDao.findAll();
return list;
}
@Override
public PaginationResult<ShiroUser> findAllByPage(Pagination<ShiroUser> pagination){
SpecificationUtil<ShiroUser> specificationUtil = new SpecificationUtil<ShiroUser>();
Map<String, Object> searchParams = new HashMap<String, Object>();
ShiroUser ShiroUser = new ShiroUser();
ShiroUser = pagination.dataTable2Entry(ShiroUser, pagination);//封装前段调用的数据。
List<String> properties = new ArrayList<String>();
properties.add("id");
Sort sort = new Sort(Direction.DESC, properties);
sort= pagination.dataTableOrder(pagination,sort,properties);
String extra_search = pagination.getExtra_search();//查询条件
log.info("extra_search="+extra_search);
String paramArray[] = extra_search.split("&");
Map map = new HashMap();
for(int i =0;i<paramArray.length;i++){
String name = paramArray[i].split("=")[0];
if(paramArray[i].split("=").length==2){
String value = paramArray[i].split("=")[1];
map.put(name, value);
}else{
map.put(name, "");
}
}
if(!map.get("username").equals("")){
searchParams.put("LIKES_username", map.get("username"));
}
if(!map.get("status").equals("")){
searchParams.put("EQS_status", map.get("status"));
}
log.info("searchParams.toString()=="+searchParams.toString());
Specification<ShiroUser> specification = specificationUtil.buildSpecification(searchParams,"and");
int page= pagination.getStart()/pagination.getPageSize();
PageRequest PageRequest = new PageRequest( page,pagination.getPageSize(), sort);
Page<ShiroUser> list = entityDao.findAll(specification, PageRequest);
PaginationResult<ShiroUser> pa=new PaginationResult();
pa.setData(list.getContent());
pa.setRecordsFiltered(list.getTotalElements());
pa.setRecordsTotal(list.getTotalElements());
pa.setDraw(new Integer(pagination.getDraw()));
return pa;
}
@Override
@Autowired
public void setEntityDao(ShiroUserDao entityDao) {
this.entityDao = entityDao;
}
}

64
demo-shiro-web/pom.xml Normal file
View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shiro-springboot-demo</artifactId>
<groupId>demo.xinwin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-shiro-web</artifactId>
<dependencies>
<dependency>
<groupId>demo.xinwin</groupId>
<artifactId>demo-shiro-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>${springboot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>1.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,31 @@
package com.xinwei;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringBootApplication
@ComponentScan(basePackages = {"com.xinwei"})
@EnableJpaRepositories("com.xinwei.dao")
public class ServerApplication implements CommandLineRunner {
@Override
public void run(String... args) {
log.info("初始化系统...");
}
public static void main(String[] args) throws Exception {
SpringApplication.run(ServerApplication.class, args);
}
}

View File

@@ -0,0 +1,70 @@
package com.xinwei.common;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public RedisTemplate<String, Object> objectRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
return template;
}
}

View File

@@ -0,0 +1,53 @@
package com.xinwei.common;
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
public class RedisUtil<T> {
public static <T> void set(RedisTemplate<String, T> template, String key, T value) {
ValueOperations<String, T> vopt = template.opsForValue();
vopt.set(key, value);
}
public static <T> void set(RedisTemplate<String, T> template, String key, T value, long time) {
ValueOperations<String, T> vopt = template.opsForValue();
vopt.set(key, value, time, TimeUnit.SECONDS);
}
public static <T> T get(RedisTemplate<String, T> template, String key) {
ValueOperations<String, T> vopt = template.opsForValue();
return vopt.get(key);
}
public static <T> void del(RedisTemplate<String, T> template, String key) {
template.delete(key);
}
public static <T> boolean hasKey(RedisTemplate<String, T> template, String key) {
return template.hasKey(key);
}
public static <T> void hset(RedisTemplate<String, T> template, String key, String field, T value) {
HashOperations<String, String, T> hopt = template.opsForHash();
hopt.put(key, field, value);
}
public static <T> T hmget(RedisTemplate<String, T> template, String key, String field) {
HashOperations<String, String, T> hopt = template.opsForHash();
return hopt.get(key, field);
}
public static <T> void hdel(RedisTemplate<String, T> template, String key, String field) {
HashOperations<String, String, T> hopt = template.opsForHash();
hopt.delete(key, field, field);
}
public static <T> boolean hexists(RedisTemplate<String, T> template, String key, String field) {
HashOperations<String, String, T> hopt = template.opsForHash();
return hopt.hasKey(key, field);
}
}

View File

@@ -0,0 +1,501 @@
package com.xinwei.control;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.service.ShiroRoleService;
import com.xinwei.service.ShiroUserService;
import com.xinwei.shiro.MyShiroRealm;
import com.xinwei.shirofunction.Function;
import com.xinwei.shirofunction.FunctionService;
import com.xinwei.shirofunction.FunctionTreeBean;
import com.xinwei.shirofunction.ShiroRole;
import com.xinwei.utils.ResponseJson;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.*;
/**
* 系统功能管理模块
*
* @create 2016年1月13日
*/
@Controller
@Slf4j
public class SysController {
@Autowired
MyShiroRealm myShiroRealm;
@Autowired
ShiroUserService shiroUserService;
@Autowired
ShiroRoleService shiroRoleService;
@Autowired
FunctionService functionService;
/**
* 进入角色列表页面
*
* @param model
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/role_manager")
public String role_manager(Model model) {
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
return "admin/sysFunctionManager/role_manager";
}
/**
* 进入功能列表页面
*
* @param model
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/function_manager")
public String function_manager(Model model) {
return "admin/sysFunctionManager/function_manager";
}
/**
*
* 角色列表
*
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/role_manager/list")
@ResponseBody
String findRoleManagerList(@RequestBody Pagination<ShiroRole> pagination) {
PaginationResult<ShiroRole> pageResonse = shiroRoleService.findAllByPage(pagination);
JSONObject jsonObject = (JSONObject) JSON.toJSON(pageResonse);
log.info(jsonObject.toJSONString());
return jsonObject.toJSONString(pageResonse, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
*
* 功能列表
*
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/function_manager/list")
@ResponseBody
String findFunctionManagerList(@RequestBody Pagination<Function> pagination) {
PaginationResult<Function> pageResonse = functionService.findAllByPage(pagination);
JSONObject jsonObject = (JSONObject) JSON.toJSON(pageResonse);
log.info(jsonObject.toJSONString());
return jsonObject.toJSONString(pageResonse, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
* 添加功能
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/addFunction")
@ResponseBody
public String addFunction(@RequestParam("pid") String pid,@RequestParam("functionName") String functionName,@RequestParam("permissionName") String permissionName) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
try {
Function function = functionService.findByPermissionName(permissionName);
if(function!=null){
responseJson.setMsg("exist");
}else {
function = new Function();
function.setCreateTime(new Date());
function.setPermissionName(permissionName);
function.setFunctionName(functionName);
function.setPid(new Integer(pid));
functionService.save(function);
}
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 删除功能
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/delFunction")
@ResponseBody
public String delFunction(String id) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
try {
List<Function> list = functionService.findListByPid(new Integer(id));
if(list!=null&&!list.isEmpty()){
responseJson.setMsg("existChildren");//存在子节点
}else {
Function function = functionService.findById(new Integer(id));
functionService.delete(function);
}
}catch(DataIntegrityViolationException ee){
responseJson.setMsg("existRoleFunction");
}
catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
*
* 进入修改功能页面
*
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/toEditFunction")
@ResponseBody
String toEditFunction(String id) {
Function function= functionService.findById(new Integer(id));
return JSONObject.toJSONString(function, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
* 功能修改
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/editFunction")
@ResponseBody
public String editFunction(Function function) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
try {
Function functionTemp = functionService.findByPermissionName(function.getPermissionName());
if(functionTemp!=null&&functionTemp.getId()!=function.getId()){
responseJson.setMsg("exist");
}else{
functionTemp = functionService.findById(function.getId());
functionTemp.setCreateTime(new Date());
functionTemp.setFunctionName(function.getFunctionName());
functionTemp.setPermissionName(function.getPermissionName());
functionService.save(functionTemp);
}
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 添加角色
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/addRole")
@ResponseBody
public String addRole(ShiroRole shiroRole) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
try {
ShiroRole shiroRoleTemp = shiroRoleService.findByRoleName(shiroRole.getRoleName());
if(shiroRoleTemp!=null){
responseJson.setMsg("exist");
}else if (shiroRole.getRoleName().equals("admin")){//内置超级管理员权限,不可以重复注册
responseJson.setMsg("admin");
}else{
shiroRole.setCreateTime(new Date());
shiroRoleService.save(shiroRole);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
}
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 进入修改角色页面
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/toEditRolePage")
@ResponseBody
public String toEditRolePage(String id) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
ShiroRole shiroRoleTemp = shiroRoleService.findById(new Integer(id));
return JSONObject.toJSONString(shiroRoleTemp);
}
/**
* 修改角色
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/editRole")
@ResponseBody
public String editRole(ShiroRole shiroRole) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
if(shiroRoleService.findById(shiroRole.getId()).getRoleName().equals("管理员")){
responseJson.setMsg("admin");
return JSONObject.toJSONString(responseJson);
}
try {
ShiroRole shiroRoleTemp1 = shiroRoleService.findByRoleName(shiroRole.getRoleName());
ShiroRole shiroRoleTemp2 = shiroRoleService.findById(shiroRole.getId());
if(shiroRoleTemp1!=null&&shiroRoleTemp1.getId()!= shiroRole.getId()){
responseJson.setMsg("exist");
}else{
shiroRoleTemp2.setCreateTime(new Date());
shiroRoleTemp2.setRoleName(shiroRole.getRoleName());
shiroRoleService.save(shiroRoleTemp2);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
}
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 删除角色
* @param id
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/delRole/{id}")
@ResponseBody
String toSystemOrgManagerEditPage(@PathVariable("id") String id) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
try {
ShiroRole shiroRole = shiroRoleService.findById(new Integer(id));
if(shiroRole.getRoleName().equals("管理员")){
responseJson.setMsg("admin");
}else{
shiroRoleService.delete(shiroRole);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
}
}catch(DataIntegrityViolationException e){
responseJson.setMsg("exist");
log.info(e.toString());
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 进入角色列表页面
*
* @param model
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/function_tree")
public String function_tree() {
return "admin/sysFunctionManager/function_tree";
}
/**
* 给角色添加功能进入功能tree页面
*
* @param model
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/role_function_tree")
public String role_function_tree() {
return "admin/sysFunctionManager/role_function_tree";
}
/**
*
* 获取目录tree列表数据-添加功能
*
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/initTree/list")
@ResponseBody
String initTree() {
List<Function> list = functionService.findList();
List<FunctionTreeBean> list2 =new ArrayList<>();
for(Function function:list) {
FunctionTreeBean functionTreeBean = new FunctionTreeBean();
functionTreeBean.setId(function.getId());
functionTreeBean.setPId(function.getPid());
functionTreeBean.setName(function.getFunctionName());
list2.add(functionTreeBean);
}
return JSONObject.toJSONString(list2, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
*
* 获取目录tree列表数据-给角色添加功能,回显功能。
*
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/roleFucntionTreeData")
@ResponseBody
String roleFucntionTreeData(String roleId) {
List<FunctionTreeBean> list2 =new ArrayList<>();
Map map =new HashMap<>();
ShiroRole shiroRole = shiroRoleService.findById(new Integer(roleId));
List<Function> list_1 = shiroRole.getFunctionList();
for(Function function:list_1){
map.put(function.getId(), true);
}
List<Function> list = functionService.findList();
for(Function function:list) {
FunctionTreeBean functionTreeBean = new FunctionTreeBean();
functionTreeBean.setId(function.getId());
functionTreeBean.setPId(function.getPid());
functionTreeBean.setName(function.getFunctionName());
if(map.get(function.getId())!=null){
functionTreeBean.setChecked(true);
}
list2.add(functionTreeBean);
}
return JSONObject.toJSONString(list2, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
* 给角色添加功能
* @param functionIds
* @param roleId
* @return
*/
@RequestMapping(value = "/admin/sysFunctionManager/addRoleFunction")
@ResponseBody
String addRoleFunction(String functionIds,String roleId) {
ResponseJson responseJson = new ResponseJson();
responseJson.setMsg("success");
log.info("functionIds=="+functionIds);
log.info("roleId=="+roleId);
try {
ShiroRole shiroRole = shiroRoleService.findById(new Integer(roleId));
List<Function> functionList = new ArrayList<>();
if(!functionIds.equals("")){
String functionIdsArray[]= functionIds.split(",");
for(int i=0;i<functionIdsArray.length;i++){
Function function = functionService.findById(new Integer(functionIdsArray[i]));
functionList.add(function);
}
}
shiroRole.setFunctionList(functionList);
shiroRoleService.save(shiroRole);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
} catch (Exception e) {
responseJson.setMsg("exception");
log.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
}

View File

@@ -0,0 +1,625 @@
package com.xinwei.control;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xinwei.common.page.Pagination;
import com.xinwei.common.page.PaginationResult;
import com.xinwei.service.ShiroRoleService;
import com.xinwei.service.ShiroUserService;
import com.xinwei.shiro.MyShiroRealm;
import com.xinwei.shirofunction.ShiroRole;
import com.xinwei.shirofunction.ShiroUser;
import com.xinwei.shirofunction.UserRoleListCheck;
import com.xinwei.spring.boot.autoconfigure.shiro.ShiroProperties;
import com.xinwei.utils.ResponseJson;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
/**
* Shiro测试Controller
*
* @create 2016年1月13日
*/
@Controller
@Slf4j
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
MyShiroRealm myShiroRealm;
/*@Autowired
UserService userService;*/
@Autowired
ShiroUserService shiroUserService;
@Autowired
ShiroRoleService shiroRoleService;
@Autowired
private ShiroProperties shiroProperties;
@RequestMapping(value = "login", method = RequestMethod.GET)
public String loginForm(Model model) {
logger.info("--info--");
log.debug("--debug--");
model.addAttribute("user", new ShiroUser());
return "login";
}
@RequestMapping(value = "/index")
public String index() {
return "login";
}
@RequestMapping(value = "/")
public String login() {
return "login";
}
@RequestMapping(value = "/regist")
public String regist() {
return "regist";
}
@RequestMapping(value = "/forgetPwd")
public String forgetPwd() {
return "forgetPwd";
}
/**
* 修改密码
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/user/password")
@ResponseBody
public String password(String password, String oldpassword, String username) {
ResponseJson responseJson = new ResponseJson();
ShiroUser user = new ShiroUser();
try {
user = shiroUserService.findByUsername(username);
oldpassword = new Md5Hash(oldpassword, "www",1024).toBase64();
if (!oldpassword.equals(user.getPassword())) {
responseJson.setMsg("passwordError");
} else {
user.setPassword(new Md5Hash(password, "www", 1024).toBase64());
shiroUserService.save(user);
responseJson.setMsg("success");
}
} catch (Exception e) {
responseJson.setMsg("exception");
logger.info(e.toString());
}
logger.info(JSONObject.toJSONString(responseJson));
return JSONObject.toJSONString(responseJson);
}
/**
* 校验用户名或者邮箱是否存在
*
* @param user
* @return
*/
@RequestMapping(value = "/checkNameOrEmallExist")
@ResponseBody
public String checkNameOrEmallExist(ShiroUser shiroUser) {
Map<String, String> map=new HashMap<String,String>();
ResponseJson responseJson = new ResponseJson();
try {
responseJson = shiroUserService.checkNameOrEmallExist(shiroUser);
if("true".equals(responseJson.getMsg())){
map.put("valid", "true");
return JSONObject.toJSONString(map);
}else{
map.put("valid", "false");
return JSONObject.toJSONString(map);
}
} catch (Exception e) {
map.put("valid", "true");
logger.info(e.toString());
}
logger.info(JSONObject.toJSONString(responseJson));
return JSONObject.toJSONString(map);
}
/**
* 管理员在后台修改 用户 用户注册,企业用户注册,管理员添加本单位用户、上级用户。
* 用户类别0-企业用户,1-本单位普通用户2-系统管理员3-上级单位
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/editUser")
@ResponseBody
public String editUser(ShiroUser shiroUser) {
ResponseJson responseJson = new ResponseJson();
try {
responseJson = shiroUserService.editUser(shiroUser);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
} catch (Exception e) {
responseJson.setMsg("exception");
logger.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 管理员在后台添加 用户 用户注册,企业用户注册,管理员添加本单位用户、上级用户。
* 用户类别0-企业用户,1-本单位普通用户2-系统管理员3-上级单位
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/addUser")
@ResponseBody
public String addUser(ShiroUser shiroUser) {
ResponseJson responseJson = new ResponseJson();
try {
responseJson = shiroUserService.addUser(shiroUser);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
if("success".equals(responseJson.getMsg())){
}
//end 添加记录日志功能
} catch (Exception e) {
responseJson.setMsg("exception");
logger.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 获取role列表以及当前用户role。
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/toAddRolePage")
@ResponseBody
public String toAddRolePage(String username) {
ResponseJson responseJson = new ResponseJson();
ShiroUser shiroUser = shiroUserService.findByUsername(username);
List<ShiroRole> roleListC = shiroUser.getRoleList();
List<ShiroRole> roleListA = shiroRoleService.findRoleList();
Map<Integer,Boolean> map =new HashMap<Integer,Boolean>();
for(int i=0;i<roleListC.size();i++){
map.put(roleListC.get(i).getId(), true);
}
List<UserRoleListCheck> list =new ArrayList<>();
for(int i=0;i<roleListA.size();i++){
UserRoleListCheck userRoleListCheck = new UserRoleListCheck();
userRoleListCheck.setUsername(shiroUser.getUsername());
userRoleListCheck.setRoleName(roleListA.get(i).getRoleName());
if(map.get(roleListA.get(i).getId())!=null){
userRoleListCheck.setCheck(true);
}
list.add(userRoleListCheck);
}
logger.info(JSONObject.toJSONString(list));
return JSONObject.toJSONString(list);
}
/**
* 用户角色修改
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/editUserRole")
@ResponseBody
public String editUserRole(String username,String role) {
logger.info(role);
ResponseJson responseJson = new ResponseJson();
try {
responseJson = shiroUserService.editUserRole(username, role);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
if("success".equals(responseJson.getMsg())){
}
//end 添加记录日志功能
} catch (Exception e) {
responseJson.setMsg("exception");
responseJson.setSuccess(true);
logger.info(e.toString());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 删除
*
* @return
*/
@RequestMapping(value = "/admin/user/del/{ids}")
@ResponseBody
String Del(@PathVariable("ids") String ids) {
ResponseJson responseJson = new ResponseJson();
try {
logger.info("ids====="+ids);
responseJson = shiroUserService.del(ids);
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
} catch (Exception e) {
logger.info(e.toString());
responseJson.setMsg(e.getMessage());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 验证用户登录名是否存在,如果不存在 返回success。
*
* @param username
* @return
*/
@RequestMapping(value = "/usernameExistValid")
@ResponseBody
public String usernameExistValid(String username) {
ResponseJson responseJson = new ResponseJson();
ShiroUser shiroUserTemp = new ShiroUser();
shiroUserTemp = shiroUserService.findByUsername(username);
if (shiroUserTemp == null) {
responseJson.setMsg("success");
} else {
responseJson.setMsg("false");
}
return JSONObject.toJSONString(responseJson);
}
/**
* 重置密码
*
* @param user
* @return
*/
@RequestMapping(value = "/resetPassword")
@ResponseBody
public String resetPassword(ShiroUser shiroUser) {
ResponseJson responseJson = new ResponseJson();
try {
logger.info("shiroUser.getUsername()=" + shiroUser.getUsername());
logger.info("shiroUser.getPassword()=" + shiroUser.getPassword());
String password = new Md5Hash(shiroUser.getPassword(), "www", 1024).toBase64();
shiroUser = shiroUserService.findByUsername(shiroUser.getUsername());
shiroUser.setPassword(password);
shiroUserService.save(shiroUser);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
responseJson.setMsg("success");
return JSONObject.toJSONString(responseJson);
}
/**
* 审核
*
* @param user
* @return
*/
@RequestMapping(value = "/admin/audit")
@ResponseBody
public String audit(String auditStatus, String username) {
ResponseJson responseJson = new ResponseJson();
try {
responseJson = shiroUserService.audit(username, auditStatus);
responseJson.setMsg("success");
//begin 添加记录日志功能
Subject currentUser = SecurityUtils.getSubject();
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
} catch (Exception e) {
responseJson.setMsg(e.getMessage());
}
return JSONObject.toJSONString(responseJson);
}
/**
* 进入用户列表页面
*
* @param model
* @return
*/
@RequestMapping(value = "/admin/table_managed")
public String table_managed(Model model) {
return "admin/table_managed";
}
/**
*
* 用户列表
*
* @return
*/
@RequestMapping(value = "/admin/findUserList")
@ResponseBody
String findListByUserName(@RequestBody Pagination<ShiroUser> pagination) {
PaginationResult<ShiroUser> pageResonse = shiroUserService.findAllByPage(pagination);
JSONObject jsonObject = (JSONObject) JSON.toJSON(pageResonse);
logger.info(jsonObject.toJSONString());
return jsonObject.toJSONString(pageResonse, SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
}
/**
*
* 获取待修改用户的值
*
* @return
*/
@RequestMapping(value = "/admin/toEditUserPage")
@ResponseBody
String toEditUserPage(String username, HttpServletRequest request) {
ShiroUser shiroUser = shiroUserService.findByUsername(username);
logger.info(JSONObject.toJSONString(shiroUser));
return JSONObject.toJSONString(shiroUser);
}
/**
*
* 进入强制修改密码,完善用户信息
*
* @return
*/
@RequestMapping(value = "/admin/user/toInformationPage")
public String toInformationPage(HttpServletRequest request) {
Subject currentUser = SecurityUtils.getSubject();
String username = (String) currentUser.getPrincipal();
ShiroUser shiroUser = shiroUserService.findByUsername(username);
request.setAttribute("shiroUser", shiroUser);
return "/admin/user/information";
}
@RequestMapping(value = "/md5")
@ResponseBody
public String md5w() {
String md5 = new Md5Hash("111111", "www",1024).toBase64();
return md5;
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public String login(@Valid ShiroUser user, BindingResult bindingResult, RedirectAttributes redirectAttributes,
HttpServletRequest request, HttpServletResponse response) {
// if(bindingResult.hasErrors()){
// return "login";
// }
ResponseJson responseJson = new ResponseJson();
String username = user.getUsername();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
// token.setRememberMe(true);
// 获取当前的Subject
Subject currentUser = SecurityUtils.getSubject();
try {
// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
// 每个Realm都能在必要时对提交的AuthenticationTokens作出反应
// 所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
logger.info("对用户[" + username + "]进行登录验证..验证开始");
currentUser.login(token);
logger.info("对用户[" + username + "]进行登录验证..验证通过");
//begin 添加记录日志功能
String logOperatorName = (String) currentUser.getPrincipal();
//end 添加记录日志功能
} catch (UnknownAccountException uae) {
logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
redirectAttributes.addFlashAttribute("message", "账户不存在");
} catch (IncorrectCredentialsException ice) {
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
redirectAttributes.addFlashAttribute("message", "密码不正确");
} catch (LockedAccountException lae) {
logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
redirectAttributes.addFlashAttribute("message", "账户已锁定");
} catch (DisabledAccountException lae) {
logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户未审核");
redirectAttributes.addFlashAttribute("message", "账户未审核");
} catch (ExcessiveAttemptsException eae) {
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多");
} catch (AuthenticationException ae) {
// 通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
ae.printStackTrace();
redirectAttributes.addFlashAttribute("message", "用户名或密码不正确");
}
// 验证是否登录成功
if (currentUser.isAuthenticated()) {
logger.info("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");
SavedRequest re = WebUtils.getAndClearSavedRequest(request);
logger.info("redirect:" + ((re == null || re.getRequestUrl() == null) ? shiroProperties.getSuccessUrl()
: re.getRequestUrl()));
String url = ((re == null || re.getRequestUrl() == null) ? shiroProperties.getSuccessUrl()
: re.getRequestUrl());
ShiroUser shiroUser = shiroUserService.findByUsername(username);
responseJson.setMsg("success");
responseJson.setUrl(url);
return JSONObject.toJSONString(responseJson);
} else {
token.clear();
Map<String, String> map = (Map) redirectAttributes.getFlashAttributes();
String reason = map.get("message");
responseJson.setMsg("false");
responseJson.setReturnStr(reason);
return JSONObject.toJSONString(responseJson);// "{\"success\":true,\"msg\":false,\"returnStr\":\""+reason+"\"}"
// ;
}
}
@RequestMapping(value = "/admin/logout")
public String logout(RedirectAttributes redirectAttributes) {
// 使用权限管理工具进行用户的退出,跳出登录,给出提示信息
SecurityUtils.getSubject().logout();
// redirectAttributes.addFlashAttribute("message", "您已安全退出");
return "redirect:/login";
}
@RequestMapping(value = "/resetPasswordError")
public String resetPasswordError(RedirectAttributes redirectAttributes) {
// 使用权限管理工具进行用户的退出,跳出登录,给出提示信息
SecurityUtils.getSubject().logout();
// redirectAttributes.addFlashAttribute("message", "您已安全退出");
return "/resetPasswordError";
}
//
// public Cookie getCookie(String cName,HttpServletRequest request) throws
// Exception
// {
// Cookie cookie=null;
// Cookie[] cs=this.getRequest().getCookies();
// if(cs!=null)
// {
// for(Cookie c:cs)
// {
// String name=c.getName();
// if(cName.equals(name))
// {
// cookie=c;
// }
// }
// }
// return cookie;
// }
}

View File

@@ -0,0 +1,64 @@
package com.xinwei.shiro;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
/**
*
* 1.自定义角色鉴权过滤器(满足其中一个角色则认证通过) 2.扩展异步请求认证提示功能;
*
* @author shadow
*
*/
public class AjaxAuthorizationFilter extends AuthorizationFilter {
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// super.onAccessDenied(request, response);
HttpServletRequest httpRequest = (HttpServletRequest) request;
// HttpServletResponse httpResponse = (HttpServletResponse) response;
Subject subject = getSubject(request, response);
// If the subject isn't identified, redirect to login URL
if (subject.getPrincipal() == null) {
if (isAjaxRequest(httpRequest)) {
} else {
saveRequestAndRedirectToLogin(request, response);
}
} else {
return true;
}
return false;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
return false;
}
/**
* 判断是否为Ajax请求
*
* @param request
* HttpServletRequest
* @return 是true, 否false
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
String requestType = request.getHeader("X-Requested-With");
if (requestType != null && requestType.equals("XMLHttpRequest")) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,60 @@
package com.xinwei.shiro;
import java.io.Serializable;
import java.util.Collection;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CustomShiroSessionDAO extends AbstractSessionDAO {
private Logger log = LoggerFactory.getLogger(CustomShiroSessionDAO.class);
private ShiroSessionRepository shiroSessionRepository;
public ShiroSessionRepository getShiroSessionRepository() {
return shiroSessionRepository;
}
public void setShiroSessionRepository(ShiroSessionRepository shiroSessionRepository) {
this.shiroSessionRepository = shiroSessionRepository;
}
@Override
public void delete(Session session) {
if (session == null) {
log.error("session can not be null,delete failed");
return;
}
Serializable id = session.getId();
if (id != null)
getShiroSessionRepository().deleteSession(id);
}
@Override
public Collection<Session> getActiveSessions() {
return getShiroSessionRepository().getAllSessions();
}
@Override
public void update(Session session) throws UnknownSessionException {
getShiroSessionRepository().saveSession(session);
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
getShiroSessionRepository().saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
return getShiroSessionRepository().getSession(sessionId);
}
}

View File

@@ -0,0 +1,43 @@
package com.xinwei.shiro;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
/**
* TODO add description
*/
@Configuration
// @ConditionalOnClass({ FreeMarkerProperties.class })
@AutoConfigureAfter(FreeMarkerProperties.class)
// @ConditionalOnBean(FreeMarkerProperties.class)
// @EnableConfigurationProperties(FreeMarkerProperties.class)
public class FreemarkerConfiguration {
@Autowired
protected FreeMarkerProperties properties;
protected void applyProperties(FreeMarkerConfigurationFactory factory) {
factory.setTemplateLoaderPaths(this.properties.getTemplateLoaderPath());
factory.setPreferFileSystemAccess(this.properties.isPreferFileSystemAccess());
factory.setDefaultEncoding(this.properties.getCharsetName());
Properties settings = new Properties();
settings.putAll(this.properties.getSettings());
factory.setFreemarkerSettings(settings);
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new ShiroTagFreeMarkerConfigurer();
applyProperties(configurer);
return configurer;
}
}

View File

@@ -0,0 +1,99 @@
package com.xinwei.shiro;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SimpleSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import com.xinwei.common.RedisUtil;
import com.xinwei.utils.Constants;
public class JedisShiroSessionRepository implements ShiroSessionRepository {
private static Logger logger = LoggerFactory.getLogger(JedisShiroSessionRepository.class);
private RedisTemplate<String, Object> objectRedisTemplate;
// @Autowired
// RedisTemplate<Object, Object> redisTemplate;
@Override
public void saveSession(Session session) {
if (session == null || session.getId() == null) {
logger.error("session或者session id为空");
return;
}
// 因为CustomSessionListener中的超时事件,必须在redis中的session存在时才会触发,
// 所以为保证该事件的触发,需要确保在本地中的session超时的时候,redis中的session还依然存在,
// 此处X2是为了保证该session在自动回话管理中能够删除
String session_key = getRedisSessionKey(session.getId());
long timeOut = session.getTimeout() / 1000 * 2;
RedisUtil.set(objectRedisTemplate, session_key, session, timeOut);
}
@Override
public void deleteSession(Serializable sessionId) {
logger.debug("删除session:" + sessionId);
if (sessionId == null) {
logger.error("id为空");
return;
}
String session_key = getRedisSessionKey(sessionId);
RedisUtil.del(objectRedisTemplate, session_key);
//TODO 更新数据库在线状态
}
@Override
public Session getSession(Serializable sessionId) {
// logger.debug("取得session:" + sessionId);
if (sessionId == null) {
logger.error("id为空");
return null;
}
String session_key = getRedisSessionKey(sessionId);
// if(!RedisUtil.hasKey(objectRedisTemplate, session_key)){
// return null;
// }
Session session = (SimpleSession) RedisUtil.get(objectRedisTemplate, session_key);
return session;
}
@Override
public Collection<Session> getAllSessions() {
logger.debug("取得所有session");
Set<Session> sessions = new HashSet<Session>();
String session_ids = Constants.REDIS_SHIRO_SESSION + "*";
Set<String> keys = objectRedisTemplate.keys(session_ids);
List<Object> objs = objectRedisTemplate.opsForValue().multiGet(keys);
for (Object obj : objs) {
Session s = (Session) obj;
sessions.add(s);
}
return sessions;
}
/**
* 获取redis中的session key
*
* @param sessionId
* @return
*/
private String getRedisSessionKey(Serializable sessionId) {
return Constants.REDIS_SHIRO_SESSION + sessionId;
}
public RedisTemplate<String, Object> getObjectRedisTemplate() {
return objectRedisTemplate;
}
public void setObjectRedisTemplate(RedisTemplate<String, Object> objectRedisTemplate) {
this.objectRedisTemplate = objectRedisTemplate;
}
}

View File

@@ -0,0 +1,102 @@
package com.xinwei.shiro;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.BeanInitializationException;
/**
* 继承 ShiroFilterFactoryBean 处理拦截资源文件问题。
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年3月8日
*/
public class MShiroFilterFactoryBean extends ShiroFilterFactoryBean {
// 对ShiroFilter来说需要直接忽略的请求
private Set<String> ignoreExt;
public MShiroFilterFactoryBean() {
super();
ignoreExt = new HashSet<>();
ignoreExt.add(".jpg");
ignoreExt.add(".png");
ignoreExt.add(".gif");
ignoreExt.add(".bmp");
ignoreExt.add(".js");
ignoreExt.add(".css");
}
@Override
protected AbstractShiroFilter createInstance() throws Exception {
org.apache.shiro.mgt.SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
return new MSpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
private final class MSpringShiroFilter extends AbstractShiroFilter {
protected MSpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
@Override
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
String str = request.getRequestURI().toLowerCase();
// 因为ShiroFilter 拦截所有请求在上面我们配置了urlPattern 为 * 当然你也可以在那里精确的添加要处理的路径这样就不需要这个类了而在每次请求里面都做了session的读取和更新访问时间等操作这样在集群部署session共享的情况下数量级的加大了处理量负载。
// 所以我们这里将一些能忽略的请求忽略掉。
// 当然如果你的集群系统使用了动静分离处理静态资料的请求不会到Filter这个层面便可以忽略。
boolean flag = true;
int idx = 0;
if(( idx = str.indexOf(".")) > 0){
str = str.substring(idx);
if(ignoreExt.contains(str.toLowerCase()))
flag = false;
}
if(flag){
super.doFilterInternal(servletRequest, servletResponse, chain);
}else{
chain.doFilter(servletRequest, servletResponse);
}
}
}
}

View File

@@ -0,0 +1,115 @@
package com.xinwei.shiro;
import java.util.List;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.xinwei.service.ShiroUserService;
import com.xinwei.shirofunction.ShiroRole;
import com.xinwei.shirofunction.ShiroUser;
import com.xinwei.utils.Constants;
/**
* MyShiroRealm
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年1月13日
*/
public class MyShiroRealm extends AuthorizingRealm{
private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);
@Autowired
private ShiroUserService shiroUserService;
/**
* 权限认证为当前登录的Subject授予角色和权限
* @see本例中该方法的调用时机为需授权资源被访问时
* @see 并且每次访问需授权资源时都会执行该方法中的逻辑这表明本例中默认并未启用AuthorizationCache
* @see 如果连续访问同一个URL比如刷新该方法不会被重复调用Shiro有一个时间间隔也就是cache时间在ehcache-shiro.xml中配置超过这个时间间隔再刷新页面该方法会被执行
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
logger.info("##################执行Shiro权限认证##################");
//获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next();
String loginName = (String)super.getAvailablePrincipal(principalCollection);
//到数据库查是否有此对象
ShiroUser user= shiroUserService.findByUsername(loginName);// 实际项目中这里可以根据实际情况做缓存如果不做Shiro自己也是有时间间隔机制2分钟内不会重复执行该方法
if(user!=null){
//权限信息对象info,用来存放查出的用户的所有的角色role及权限permission
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//用户的角色集合
info.setRoles(user.getRolesName());
// //用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的四行可以不要
List<ShiroRole> roleList=user.getRoleList();
for (ShiroRole role : roleList) {
info.addStringPermissions(role.getPermissionsName());
}
// 或者按下面这样添加
// 添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色
// info.addRole("admin");
//添加权限
// info.addStringPermission("admin:manage");
logger.info("已为用户[mike]赋予了[admin]角色和[admin:manage]权限");
return info;
}
// 返回null的话就会导致任何用户访问被拦截的请求时都会自动跳转到unauthorizedUrl指定的地址
return null;
}
/**
* 登录认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
//UsernamePasswordToken对象用来存放提交的登录信息
UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
logger.info("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
//查出是否有此用户
ShiroUser user= shiroUserService.findByUsername(token.getUsername());
if(user==null){
throw new UnknownAccountException();
}
if(user!=null&&user.getStatus().equals(Constants.userStatus_2)){
throw new LockedAccountException();
}
if(user!=null&&user.getStatus().equals(Constants.userStatus_0)){
throw new DisabledAccountException();
}
if(user!=null&&user.getStatus().equals(Constants.userStatus_1)){
// 若存在将此用户存放到登录认证info中无需自己做密码对比Shiro会为我们进行密码对比校验
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes("www"),getName());
}
return null;
}
}

View File

@@ -0,0 +1,37 @@
package com.xinwei.shiro;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class ShiroConfiguration {
/**
* 注释掉该方法时 shiro的登录会话session由ehcache保持。
* 打开该方法时shiro的登录回话session由redis保持。
* @param jedisShiroSessionRepository
* @return
*/
@Bean
@DependsOn(value = { "jedisShiroSessionRepository" })
public SessionDAO sessionDAO(JedisShiroSessionRepository jedisShiroSessionRepository) {
final CustomShiroSessionDAO customShiroSessionDAO = new CustomShiroSessionDAO();
customShiroSessionDAO.setShiroSessionRepository(jedisShiroSessionRepository);
return customShiroSessionDAO;
}
@Bean
@DependsOn(value = { "objectRedisTemplate" })
public JedisShiroSessionRepository jedisShiroSessionRepository(RedisTemplate<String, Object> objectRedisTemplate) {
final JedisShiroSessionRepository jedisShiroSessionRepository = new JedisShiroSessionRepository();
jedisShiroSessionRepository.setObjectRedisTemplate(objectRedisTemplate);
return jedisShiroSessionRepository;
}
}

View File

@@ -0,0 +1,16 @@
package com.xinwei.shiro;
import java.io.Serializable;
import java.util.Collection;
import org.apache.shiro.session.Session;
public interface ShiroSessionRepository {
void saveSession(Session session);
void deleteSession(Serializable sessionId);
Session getSession(Serializable sessionId);
Collection<Session> getAllSessions();
}

View File

@@ -0,0 +1,17 @@
package com.xinwei.shiro;
import java.io.IOException;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import com.xinwei.shiro.tag.ShiroTags;
import freemarker.template.TemplateException;
public class ShiroTagFreeMarkerConfigurer extends FreeMarkerConfigurer{
@Override
public void afterPropertiesSet() throws IOException, TemplateException {
super.afterPropertiesSet();
this.getConfiguration().setSharedVariable("shiro", new ShiroTags());
}
}

View File

@@ -0,0 +1,48 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.Map;
/**
* JSP tag that renders the tag body only if the current user has executed a
* <b>successful</b> authentication attempt
* <em>during their current session</em>.
*
* <p>
* This is more restrictive than the {@link UserTag}, which only ensures the
* current user is known to the system, either via a current login or from
* Remember Me services, which only makes the assumption that the current user
* is who they say they are, and does not guarantee it like this tag does.
*
* <p>
* The logically opposite tag of this one is the {@link NotAuthenticatedTag}
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.AuthenticatedTag}
* </p>
*
* @since 0.2
*/
public class AuthenticatedTag extends SecureTag {
private static final Logger log = Logger.getLogger("AuthenticatedTag");
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
if (getSubject() != null && getSubject().isAuthenticated()) {
if (log.isDebugEnabled()) {
log.debug("Subject exists and is authenticated. Tag body will be evaluated.");
}
renderBody(env, body);
} else {
if (log.isDebugEnabled()) {
log.debug("Subject does not exist or is not authenticated. Tag body will not be evaluated.");
}
}
}
}

View File

@@ -0,0 +1,46 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.Map;
/**
* JSP tag that renders the tag body if the current user <em>is not</em> known
* to the system, either because they haven't logged in yet, or because they
* have no 'RememberMe' identity.
*
* <p>
* The logically opposite tag of this one is the {@link UserTag}. Please read
* that class's JavaDoc as it explains more about the differences between
* Authenticated/Unauthenticated and User/Guest semantic differences.
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.GuestTag}
* </p>
*
* @since 0.9
*/
public class GuestTag extends SecureTag {
private static final Logger log = Logger.getLogger("AuthenticatedTag");
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
if (getSubject() == null || getSubject().getPrincipal() == null) {
if (log.isDebugEnabled()) {
log.debug("Subject does not exist or does not have a known identity (aka 'principal'). "
+ "Tag body will be evaluated.");
}
renderBody(env, body);
} else {
if (log.isDebugEnabled()) {
log.debug("Subject exists or has a known identity (aka 'principal'). "
+ "Tag body will not be evaluated.");
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.xinwei.shiro.tag;
import org.apache.shiro.subject.Subject;
/**
* Displays body content if the current user has any of the roles specified.
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.HasAnyRolesTag}
* </p>
*
* @since 0.2
*/
public class HasAnyRolesTag extends RoleTag {
// Delimeter that separates role names in tag attribute
private static final String ROLE_NAMES_DELIMETER = ",";
protected boolean showTagBody(String roleNames) {
boolean hasAnyRole = false;
Subject subject = getSubject();
if (subject != null) {
// Iterate through roles and check to see if the user has one of the
// roles
for (String role : roleNames.split(ROLE_NAMES_DELIMETER)) {
if (subject.hasRole(role.trim())) {
hasAnyRole = true;
break;
}
}
}
return hasAnyRole;
}
}

View File

@@ -0,0 +1,14 @@
package com.xinwei.shiro.tag;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.HasPermissionTag}
* </p>
*
* @since 0.1
*/
public class HasPermissionTag extends PermissionTag {
protected boolean showTagBody(String p) {
return isPermitted(p);
}
}

View File

@@ -0,0 +1,12 @@
package com.xinwei.shiro.tag;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.HasRoleTag}
* </p>
*/
public class HasRoleTag extends RoleTag {
protected boolean showTagBody(String roleName) {
return getSubject() != null && getSubject().hasRole(roleName);
}
}

View File

@@ -0,0 +1,12 @@
package com.xinwei.shiro.tag;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.LacksPermissionTag}
* </p>
*/
public class LacksPermissionTag extends PermissionTag {
protected boolean showTagBody(String p) {
return !isPermitted(p);
}
}

View File

@@ -0,0 +1,13 @@
package com.xinwei.shiro.tag;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.LacksRoleTag}
* </p>
*/
public class LacksRoleTag extends RoleTag {
protected boolean showTagBody(String roleName) {
boolean hasRole = getSubject() != null && getSubject().hasRole(roleName);
return !hasRole;
}
}

View File

@@ -0,0 +1,36 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.Map;
/**
* Freemarker tag that renders the tag body only if the current user has
* <em>not</em> executed a successful authentication attempt
* <em>during their current session</em>.
*
* <p>
* The logically opposite tag of this one is the
* {@link org.apache.shiro.web.tags.AuthenticatedTag}.
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.NotAuthenticatedTag}
* </p>
*/
public class NotAuthenticatedTag extends SecureTag {
static final Logger log = Logger.getLogger("NotAuthenticatedTag");
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
if (getSubject() == null || !getSubject().isAuthenticated()) {
log.debug("Subject does not exist or is not authenticated. Tag body will be evaluated.");
renderBody(env, body);
} else {
log.debug("Subject exists and is authenticated. Tag body will not be evaluated.");
}
}
}

View File

@@ -0,0 +1,49 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModelException;
import java.io.IOException;
import java.util.Map;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.PermissionTag}
* </p>
*/
public abstract class PermissionTag extends SecureTag {
String getName(Map params) {
return getParam(params, "name");
}
@Override
protected void verifyParameters(Map params) throws TemplateModelException {
String permission = getName(params);
if (permission == null || permission.length() == 0) {
throw new TemplateModelException("The 'name' tag attribute must be set.");
}
}
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
String p = getName(params);
boolean show = showTagBody(p);
if (show) {
renderBody(env, body);
}
}
protected boolean isPermitted(String p) {
String username = (String)getSubject().getPrincipal();
if(username.equals("admin")){//超级管理员具备所有权限
return true;
}else{
return getSubject() != null && getSubject().isPermitted(p);
}
}
protected abstract boolean showTagBody(String p);
}

View File

@@ -0,0 +1,130 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModelException;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.util.Map;
/**
* <p>
* Tag used to print out the String value of a user's default principal, or a
* specific principal as specified by the tag's attributes.
* </p>
*
* <p>
* If no attributes are specified, the tag prints out the <tt>toString()</tt>
* value of the user's default principal. If the <tt>type</tt> attribute is
* specified, the tag looks for a principal with the given type. If the
* <tt>property</tt> attribute is specified, the tag prints the string value of
* the specified property of the principal. If no principal is found or the user
* is not authenticated, the tag displays nothing unless a <tt>defaultValue</tt>
* is specified.
* </p>
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.PrincipalTag}
* </p>
*
* @since 0.2
*/
public class PrincipalTag extends SecureTag {
static final Logger log = Logger.getLogger("PrincipalTag");
/**
* The type of principal to be retrieved, or null if the default principal
* should be used.
*/
String getType(Map params) {
return getParam(params, "type");
}
/**
* The property name to retrieve of the principal, or null if the
* <tt>toString()</tt> value should be used.
*/
String getProperty(Map params) {
return getParam(params, "property");
}
@SuppressWarnings("unchecked")
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
String result = null;
if (getSubject() != null) {
// Get the principal to print out
Object principal;
if (getType(params) == null) {
principal = getSubject().getPrincipal();
} else {
principal = getPrincipalFromClassName(params);
}
// Get the string value of the principal
if (principal != null) {
String property = getProperty(params);
if (property == null) {
result = principal.toString();
} else {
result = getPrincipalProperty(principal, property);
}
}
}
// Print out the principal value if not null
if (result != null) {
try {
env.getOut().write(result);
} catch (IOException ex) {
throw new TemplateException("Error writing [" + result + "] to Freemarker.", ex, env);
}
}
}
@SuppressWarnings("unchecked")
Object getPrincipalFromClassName(Map params) {
String type = getType(params);
try {
Class cls = Class.forName(type);
return getSubject().getPrincipals().oneByType(cls);
} catch (ClassNotFoundException ex) {
log.error("Unable to find class for name [" + type + "]", ex);
}
return null;
}
String getPrincipalProperty(Object principal, String property) throws TemplateModelException {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(principal.getClass());
// Loop through the properties to get the string value of the
// specified property
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
if (propertyDescriptor.getName().equals(property)) {
Object value = propertyDescriptor.getReadMethod().invoke(principal, (Object[]) null);
return String.valueOf(value);
}
}
// property not found, throw
throw new TemplateModelException("Property [" + property + "] not found in principal of type ["
+ principal.getClass().getName() + "]");
} catch (Exception ex) {
throw new TemplateModelException("Error reading property [" + property + "] from principal of type ["
+ principal.getClass().getName() + "]", ex);
}
}
}

View File

@@ -0,0 +1,28 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.Map;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.RoleTag}
* </p>
*/
public abstract class RoleTag extends SecureTag {
String getName(Map params) {
return getParam(params, "name");
}
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
boolean show = showTagBody(getName(params));
if (show) {
renderBody(env, body);
}
}
protected abstract boolean showTagBody(String roleName);
}

View File

@@ -0,0 +1,47 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.template.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import java.io.IOException;
import java.util.Map;
/**
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.SecureTag}
* </p>
*/
public abstract class SecureTag implements TemplateDirectiveModel {
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
throws TemplateException, IOException {
verifyParameters(params);
render(env, params, body);
}
public abstract void render(Environment env, Map params, TemplateDirectiveBody body)
throws IOException, TemplateException;
protected String getParam(Map params, String name) {
Object value = params.get(name);
if (value instanceof SimpleScalar) {
return ((SimpleScalar) value).getAsString();
}
return null;
}
protected Subject getSubject() {
return SecurityUtils.getSubject();
}
protected void verifyParameters(Map params) throws TemplateModelException {
}
protected void renderBody(Environment env, TemplateDirectiveBody body) throws IOException, TemplateException {
if (body != null) {
body.render(env.getOut());
}
}
}

View File

@@ -0,0 +1,26 @@
package com.xinwei.shiro.tag;
import freemarker.template.SimpleHash;
/**
* Shortcut for injecting the tags into Freemarker
*
* <p>
* Usage: cfg.setSharedVeriable("shiro", new ShiroTags());
* </p>
*/
public class ShiroTags extends SimpleHash {
public ShiroTags() {
put("authenticated", new AuthenticatedTag());
put("guest", new GuestTag());
put("hasAnyRoles", new HasAnyRolesTag());
put("hasPermission", new HasPermissionTag());
put("hasRole", new HasRoleTag());
put("lacksPermission", new LacksPermissionTag());
put("lacksRole", new LacksRoleTag());
put("notAuthenticated", new NotAuthenticatedTag());
put("principal", new PrincipalTag());
put("user", new UserTag());
put("username", new UsernameTag());
}
}

View File

@@ -0,0 +1,46 @@
package com.xinwei.shiro.tag;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.util.Map;
/**
* Freemarker tag that renders the tag body if the current user known to the
* system, either from a successful login attempt (not necessarily during the
* current session) or from 'RememberMe' services.
*
* <p>
* <b>Note:</b> This is <em>less</em> restrictive than the
* <code>AuthenticatedTag</code> since it only assumes the user is who they say
* they are, either via a current session login <em>or</em> via Remember Me
* services, which makes no guarantee the user is who they say they are. The
* <code>AuthenticatedTag</code> however guarantees that the current user has
* logged in <em>during their current session</em>, proving they really are who
* they say they are.
*
* <p>
* The logically opposite tag of this one is the
* {@link org.apache.shiro.web.tags.GuestTag}.
*
* <p>
* Equivalent to {@link org.apache.shiro.web.tags.UserTag}
* </p>
*/
public class UserTag extends SecureTag {
static final Logger log = Logger.getLogger("UserTag");
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
if (getSubject() != null && getSubject().getPrincipal() != null) {
log.debug("Subject has known identity (aka 'principal'). Tag body will be evaluated.");
renderBody(env, body);
} else {
log.debug(
"Subject does not exist or have a known identity (aka 'principal'). Tag body will not be evaluated.");
}
}
}

View File

@@ -0,0 +1,39 @@
package com.xinwei.shiro.tag;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.shiro.subject.PrincipalCollection;
import freemarker.core.Environment;
import freemarker.log.Logger;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
public class UsernameTag extends SecureTag {
static final Logger log = Logger.getLogger("UsernameTag");
@Override
public void render(Environment env, Map params, TemplateDirectiveBody body) throws IOException, TemplateException {
String result = null;
if (getSubject() != null) {
PrincipalCollection pcpls = getSubject().getPrincipals();
Set<String> set = pcpls.getRealmNames();
Iterator<String> it = set.iterator();
if (it.hasNext()) {
result = it.next();
}
}
// Print out the principal value if not null
if (result != null) {
try {
env.getOut().write(result);
} catch (IOException ex) {
throw new TemplateException("Error writing [" + result + "] to Freemarker.", ex, env);
}
}
}
}

View File

@@ -0,0 +1,54 @@
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shiroDemo?useUnicode=true&characterEncoding=utf-8&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.max-active=20
spring.datasource.max-idle=10
spring.datasource.min-idle=5
spring.datasource.default-auto-commit=false
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=false
spring.datasource.test-on-return=false
spring.datasource.validation-query=SELECT 1
#连接Idle10分钟后超时每1分钟检查一次
spring.datasource.time-between-eviction-runs-millis=60000
spring.datasource.min-evictable-idle-time-millis=600000
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.pool.max-idle=20
spring.redis.pool.min-idle=1
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=1000
spring.redis.timeout=0
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.expose-spring-macro-helpers=true
spring.freemarker.request-context-attribute=request
#spring.freemarker.default-encoding=UTF-8
spring.freemarker.settings.template_update_delay=0
spring.freemarker.settings.number_format=0.##########
spring.freemarker.settings.datetime_format=yyyy-MM-dd HH:mm:ss
spring.freemarker.settings.classic_compatible=true
spring.freemarker.settings.template_exception_handler=ignore
spring.freemarker.suffix=.ftl
spring.freemarker.templateEncoding=UTF-8
spring.freemarker.templateLoaderPath=classpath:/templates/
server.port=8080
server.contextPath=/

View File

@@ -0,0 +1,23 @@
shiro:
realm-class: com.xinwei.shiro.MyShiroRealm
custom-authc-filter-class: com.xinwei.shiro.AjaxAuthorizationFilter
login-url: /login
success-url: /admin/sysFunctionManager/role_manager
unauthorized-url: /403
retry-max: 10000
sign-in:
user-param: username
password-param: password
remember-me-param: rememberMe
hash-iterations: 1024
hash-algorithm-name: MD5
stored-credentials-hex-encoded: false
session:
global-session-timeout: 180000
validation-interval: 1000
validation-scheduler-enabled: true
filter-chain-definitions:
/media/**: anon
/user/edit/*: authc,perms[user:edit]
/admin/**: authc

View File

@@ -0,0 +1,21 @@
log4j.rootLogger=INFO, console
#log4j.rootLogger=INFO, console, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%p]-[%c] %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=logs/thirdparty.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%p]-[%c] %m%n
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

View File

@@ -0,0 +1,256 @@
var FunctionManaged = function () {
var pid="";
var pidFunctionName="";
var flag=false;
return {
//main function to initiate the module
init: function () {
FunctionManaged.flag=true;
table=$('#sample_1').DataTable({
"processing": false,
"serverSide": false,
"searching":false,
"autoWidth":false,
"lengthChange": false,
"bPaginate":false,//是否使用分页
"bInfo": false,//页脚信息
"ajax": {
"url": "/admin/sysFunctionManager/function_manager/list",
"type": "POST",
"dataType": "json",
"contentType":"application/json",
"data": function ( d ) {
d.extra_search =FunctionManaged.pid;
return JSON.stringify( d );
}
},
"aaSorting": [],
"columns": [
{ "data": "functionName","bSortable": false,"searchable":true},
{ "data": "permissionName","bSortable": false,"searchable":true},
{ "data": "createTime","bSortable": false,"searchable":true}
],
});
},
initButton: function () {
FunctionManaged.pid="";
$("#addFunction").on('click',function(){
if(FunctionManaged.pid==""){
appcommon.alert("请选择目录",0,2000);
}else{
//modal模式框bug的处理清除上一次输入的值。
$('#functionName').val("");
$('#permissionName').val("");
//本次选中的上一级目录的值
$('#pidFunctionName').val(FunctionManaged.pidFunctionName);
$('#pid').val(FunctionManaged.pid);
$('#Modal-AddFunction').modal('show')
}
});
$("#delFunction").on('click',function(){
if(!FunctionManaged.flag||FunctionManaged.pid==""){
appcommon.alert("请选择目录",0,2000);
}else{
delFunction(FunctionManaged.pid);
}
});
$("#editFunction").on('click',function(){
if(FunctionManaged.pid==""){
appcommon.alert("请选择目录",0,2000);
}else{
toEditFuntion();
}
});
},
reloadList: function (name,id) {
FunctionManaged.pidFunctionName=name;
FunctionManaged.pid=id;
if(!FunctionManaged.flag){
FunctionManaged.init();
}else{
table.ajax.reload();
}
}
};
}();
function initTree(){
var zNodes;
$.ajax({
url:'/admin/sysFunctionManager/initTree/list',
type:'POST',
async: false,
dataType: "json",
success:function(data){
zNodes = data;
}
});
return zNodes;
}
function addFunctionSubmit(){
var pid=$("#pid").val();
var functionName=$("#functionName").val();
var permissionName= $("#permissionName").val();
$.ajax({
url:'/admin/sysFunctionManager/addFunction',
type:'post',
data:'pid='+pid+"&functionName="+functionName+"&permissionName="+permissionName,
async : true,// 默认为true 异步
error:function(){
appcommon.alert("系统异常",2);
},
success:function(data){
var data = $.parseJSON(data);
if(data.msg=="exist"){
appcommon.alert("功能编码重复,请重新填写",2,2000);
} else if(data.msg=="success"){
appcommon.alert("添加成功",1,2000);
reloadTree();
}else{
appcommon.alert("系统异常",0,2000);
}
$('#Modal-AddFunction').modal('close')
}
});
}
function delFunction(id){
layer.confirm('确定吗?', {icon: 3, title:'提示'}, function(index){
$.ajax({
url:'/admin/sysFunctionManager/delFunction',
type:'post',
data:'id='+id,
async : true,// 默认为true 异步
error:function(){
appcommon.alert("系统异常",2);
},
success:function(data){
var data = $.parseJSON(data);
if(data.msg=="existChilden"){
appcommon.alert("请先删除子目录",2,2000);
}else if(data.msg=="existRoleFunction"){
appcommon.alert("该功能已被角色绑定,请先解除绑定",2,2000);
} else if(data.msg=="success"){
appcommon.alert("删除成功",1,2000);
reloadTree();
}else{
appcommon.alert("系统异常",0,2000);
}
}
});
layer.close(index);
});
}
function reloadTree(){
FunctionManaged.pidFunctionName="";
FunctionManaged.pid="";
window.iframepage.reloadTree();
}
/**
* 获取待修改功能的值
*/
function toEditFuntion(){
$.ajax({
url:'/admin/sysFunctionManager/toEditFunction',
type:'post',
data:'id='+FunctionManaged.pid,
async : true,// 默认为true 异步
error:function(){
appcommon.alert("系统异常",2);
},
success:function(data){
var data = $.parseJSON(data);
$("#editFunction-form input[name=functionName]").val(data.functionName)
$("#editFunction-form input[name=id]").val(data.id)
$("#editFunction-form input[name=permissionName]").val(data.permissionName)
$('#Modal-EditFunction').modal('show')
}
});
}
/**
* 功能修改-提交
*/
function editFunctionSubmit(){
var formvalue= $("#editFunction-form").serialize();
$.ajax({
url:'/admin/sysFunctionManager/editFunction',
type:'POST',
dataType: "json",
data:formvalue,
success:function(data){
if (data.msg=='success'){
appcommon.alert("修改成功",1,2000);
reloadTree();
}else if(data.msg=='exist'){
appcommon.alert("功能编码重复,请重新填写,",2,2000);
}else{
appcommon.alert("系统异常",2,2000);
}
}
});
}

View File

@@ -0,0 +1,388 @@
var RoleManaged = function () {
return {
//main function to initiate the module
init: function () {
table=$('#sample_1').DataTable({
"processing": true,
"serverSide": true,
"searching":false,
"autoWidth":false,
"ajax": {
"url": "/admin/sysFunctionManager/role_manager/list",
"type": "POST",
"dataType": "json",
"contentType":"application/json",
"data": function ( d ) {
return JSON.stringify( d );
}
},
"aaSorting": [],
"columns": [
{
data: "id",
bSortable:false,
render: function ( data, type, row ) {
return '<input type="checkbox" name="selecevalue" value='+data+' class="editor-active">';
}
},
{ "data": "roleName","bSortable": false,"searchable":true},
{ "data": "createTime","bSortable": true,"searchable":true}
],
// set the initial value
"aLengthMenu": [
[5, 15, 20],
[5, 15, 20] // change per page values here
],
"iDisplayLength":5,
"oLanguage": {
"sLengthMenu": "每页显示 _MENU_ 条记录",
"sZeroRecords": "抱歉, 没有找到",
"sInfo": "从 _START_ 到 _END_ /共 _TOTAL_ 条数据",
"sInfoEmpty": "没有数据",
"sInfoFiltered": "(从 _MAX_ 条数据中检索)",
"sSearch": "搜索",
"sProcessing": "处理中...",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "前一页",
"sNext": "后一页",
"sLast": "尾页"
},
"sZeroRecords": "没有检索到数据",
},
});
$("#addRole").on('click',function(){
$('#Modal-AddRole').modal('show')
});
$("#editRole").on('click',function(){
var arr= setSelectAll();
if(arr[0]>1){
appcommon.alert("每次只能修改一条记录",0,2000);
return;
}
if(arr[0]==0){
appcommon.alert("请选择记录",0,2000);
return ;
}
toEditRolePage(arr[1]);
});
$("#addRoleFunction").on('click',function(){
var arr= setSelectAll();
if(arr[0]>1){
appcommon.alert("每次只能操作一条记录",0,2000);
return;
}
if(arr[0]==0){
appcommon.alert("请选择记录",0,2000);
return ;
}
addRoleFunction(arr[1]);
});
$("#delRole").on('click',function(){
var arr= setSelectAll();
if(arr[0]>1){
appcommon.alert("每次只能修改一条记录",0,2000);
return;
}
if(arr[0]==0){
appcommon.alert("请选择记录",0,2000);
return ;
}
delRole(arr[1]);
});
},
reload: function () {
table.ajax.reload();
}
};
}();
function addRoleSubmit(){
if($("#roleName").val()==""){
appcommon.alert("请添加角色名称",2,2000);
return;
}
var formvalue= $("#addRole-form").serialize();
$.ajax({
url:'/admin/sysFunctionManager/addRole',
type:'POST',
dataType: "json",
data:formvalue,
success:function(data){
if (data.msg=='success'){
appcommon.alert("添加成功",1);
window.location.href = "/admin/sysFunctionManager/role_manager";
}else if(data.msg=='exist'){
appcommon.alert("已存在,无法重复添加",2,3000);
}else if(data.msg=='admin'){
appcommon.alert("内置超级管理员权限,不可以重复注册",2,3000);
}else{
appcommon.alert("系统异常",2);
}
}
});
}
/**
* 获取待修改用户的值
*/
function toEditRolePage(id){
$.ajax({
url:'/admin/sysFunctionManager/toEditRolePage',
type:'post',
data:'id='+id,
async : false,// 默认为true 异步
error:function(){
appcommon.alert("系统异常",2);
},
success:function(data){
var data = $.parseJSON(data);
$("#editRole-form input[name=roleName]").val(data.roleName);
$("#editRole-form input[name=id]").val(data.id);
$('#Modal-EditRole').modal('show')
}
});
}
var roleId="";
function addRoleFunction(id){
roleId = id;
var messageId = '';
var pushPageIndex = layer.open({
title:'给角色赋权限',
type: 2,
shadeClose: true,
shade: 0,
area: ['360px', '500px'],
skin: 'layui-layer-rim', //加上边框
content: '/admin/sysFunctionManager/role_function_tree',
cancel: function(){
//右上角关闭回调
layer.close(pushPageIndex);
}
,
btn: ['保存', '关闭', ]
,yes: function(index, layero){
//按钮【按钮一】的回调
// alert("成功");
var iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象
var functionIds = iframeWin.getCheckFunctionIds();
$.ajax({
url:'/admin/sysFunctionManager/addRoleFunction?functionIds='+functionIds+"&roleId="+roleId,
type:'POST',
async: false,
dataType: "json",
success:function(data){
if(data.msg=="success"){
appcommon.alert("操作成功",1,2000);
layer.close(index);
}
}
});
//下面是 不错的例子
//子页面 给父页面赋值. 父页面从子页面 获取值 但是一般都要通过jQuery去取.
//父页面 给子页面赋值.
//var body = layer.getChildFrame('body', index);
//var iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象执行iframe页的方法iframeWin.method();
//console.log(body.html()) //得到iframe页的body内容
//body.find('input').val('Hi我是从父页来的')
},btn2: function(index, layero){
//按钮【按钮二】的回调
// alert("失败");
}
});
}
function roleFucntionTreeData(){
var zNodes;
$.ajax({
url:'/admin/sysFunctionManager/roleFucntionTreeData?roleId='+roleId,
type:'POST',
async: false,
dataType: "json",
success:function(data){
zNodes = data;
}
});
return zNodes;
}
/**
* 用户信息修改-提交
*/
function editRoleSubmit(){
var formvalue= $("#editRole-form").serialize();
$.ajax({
url:'/admin/sysFunctionManager/editRole',
type:'POST',
dataType: "json",
data:formvalue,
success:function(data){
if (data.msg=='success'){
appcommon.alert("修改成功",1,2000);
window.location.href = "/admin/sysFunctionManager/role_manager";
}else if(data.msg=='exist'){
appcommon.alert("已存在,无法重复添加",2,3000);
}else if(data.msg=='admin'){
appcommon.alert("管理员角色,不可以修改!",2,3000);
}else{
appcommon.alert("系统异常",2,2000);
}
}
});
}
/**
* 删除角色
*/
function delRole(id){
layer.confirm('确定删除吗?', {icon: 3, title:'提示'}, function(index){
$.ajax({
url:'/admin/sysFunctionManager/delRole/'+id,
type:'post',
data:'',
async : false,// 默认为true 异步
success:function(data){
var data = $.parseJSON(data);
if (data.msg=='success'){
layer.alert('删除成功', function(index){
window.location.href = "/admin/sysFunctionManager/role_manager";
layer.close(index);
});
}else if(data.msg=='exist'){
layer.alert('删除失败,有用户在使用该角色,请先解除使用再删除!', function(index){
window.location.href = "/admin/sysFunctionManager/role_manager";
layer.close(index);
});
}else if(data.msg=='admin'){
layer.alert('管理员角色,不可以删除!', function(index){
layer.close(index);
});
}
else{
layer.alert('系统异常', function(index){
window.location.href = "/admin/sysFunctionManager/role_manager";
layer.close(index);
});
}
}
});
layer.close(index);
});
}
/**
* 全选,全部取消
*/
function selectAll(){
if ($("#selectall").attr("checked")) {
//$(":checkbox").attr("checked", true);
$("[name='selecevalue']:checkbox").attr("checked", true);
} else {
//$(":checkbox").attr("checked", false);
$("[name='selecevalue']:checkbox").attr("checked", false);
}
}
/**
* 获取选择复选框数据和具体哪些复选框。
*/
function setSelectAll(){
var chsub = $("input[type='checkbox'][name='selecevalue']").length; //获取subcheck的个数
var checkedsub = $("input[type='checkbox'][name='selecevalue']:checked").length; //获取选中的subcheck的个数
if (checkedsub == chsub) {
$("input[name='selectall']:checkbox").attr("checked", true);
}
var selectvalue="";
$("input[name='selecevalue']:checked").each(function(){
selectvalue+=$(this).val()+",";
})
var arr=[];
arr[0]=checkedsub;
arr[1]=selectvalue.substring(0,selectvalue.length-1)
return arr;
}

View File

@@ -0,0 +1,476 @@
/*!
* Bootstrap v3.3.4 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn-default .badge,
.btn-primary .badge,
.btn-success .badge,
.btn-info .badge,
.btn-warning .badge,
.btn-danger .badge {
text-shadow: none;
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.btn-default:hover,
.btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px;
}
.btn-default:active,
.btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.btn-default.disabled,
.btn-default:disabled,
.btn-default[disabled] {
background-color: #e0e0e0;
background-image: none;
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #245580;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #265a88;
background-position: 0 -15px;
}
.btn-primary:active,
.btn-primary.active {
background-color: #265a88;
border-color: #245580;
}
.btn-primary.disabled,
.btn-primary:disabled,
.btn-primary[disabled] {
background-color: #265a88;
background-image: none;
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #3e8f3e;
}
.btn-success:hover,
.btn-success:focus {
background-color: #419641;
background-position: 0 -15px;
}
.btn-success:active,
.btn-success.active {
background-color: #419641;
border-color: #3e8f3e;
}
.btn-success.disabled,
.btn-success:disabled,
.btn-success[disabled] {
background-color: #419641;
background-image: none;
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #28a4c9;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px;
}
.btn-info:active,
.btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9;
}
.btn-info.disabled,
.btn-info:disabled,
.btn-info[disabled] {
background-color: #2aabd2;
background-image: none;
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #e38d13;
}
.btn-warning:hover,
.btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px;
}
.btn-warning:active,
.btn-warning.active {
background-color: #eb9316;
border-color: #e38d13;
}
.btn-warning.disabled,
.btn-warning:disabled,
.btn-warning[disabled] {
background-color: #eb9316;
background-image: none;
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #b92c28;
}
.btn-danger:hover,
.btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px;
}
.btn-danger:active,
.btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28;
}
.btn-danger.disabled,
.btn-danger:disabled,
.btn-danger[disabled] {
background-color: #c12e2a;
background-image: none;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
}
.navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
}
.navbar-inverse .navbar-nav > .open > a,
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
@media (max-width: 767px) {
.navbar .navbar-nav .open .dropdown-menu > .active > a,
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
background-repeat: repeat-x;
border-color: #2b669a;
}
.list-group-item.active .badge,
.list-group-item.active:hover .badge,
.list-group-item.active:focus .badge {
text-shadow: none;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
}
/*# sourceMappingURL=bootstrap-theme.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,288 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
<font-face units-per-em="1200" ascent="960" descent="-240" />
<missing-glyph horiz-adv-x="500" />
<glyph horiz-adv-x="0" />
<glyph horiz-adv-x="400" />
<glyph unicode=" " />
<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xa0;" />
<glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
<glyph unicode="&#x2000;" horiz-adv-x="650" />
<glyph unicode="&#x2001;" horiz-adv-x="1300" />
<glyph unicode="&#x2002;" horiz-adv-x="650" />
<glyph unicode="&#x2003;" horiz-adv-x="1300" />
<glyph unicode="&#x2004;" horiz-adv-x="433" />
<glyph unicode="&#x2005;" horiz-adv-x="325" />
<glyph unicode="&#x2006;" horiz-adv-x="216" />
<glyph unicode="&#x2007;" horiz-adv-x="216" />
<glyph unicode="&#x2008;" horiz-adv-x="162" />
<glyph unicode="&#x2009;" horiz-adv-x="260" />
<glyph unicode="&#x200a;" horiz-adv-x="72" />
<glyph unicode="&#x202f;" horiz-adv-x="260" />
<glyph unicode="&#x205f;" horiz-adv-x="325" />
<glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
<glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
<glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
<glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
<glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
<glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
<glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
<glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
<glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
<glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
<glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
<glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
<glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
<glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
<glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
<glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
<glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
<glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
<glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
<glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
<glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
<glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
<glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
<glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
<glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
<glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
<glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
<glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
<glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
<glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
<glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
<glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
<glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
<glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
<glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
<glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
<glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
<glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
<glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
<glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
<glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
<glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
<glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
<glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
<glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
<glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
<glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
<glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
<glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
<glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
<glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
<glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
<glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
<glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
<glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
<glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
<glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
<glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
<glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
<glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
<glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
<glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
<glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
<glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
<glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
<glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
<glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
<glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
<glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
<glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
<glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
<glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
<glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
<glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
<glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
<glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
<glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
<glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
<glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
<glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
<glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
<glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
<glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
<glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
<glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
<glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
<glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
<glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
<glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
<glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
<glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
<glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
<glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
<glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
<glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
<glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
<glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
<glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
<glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
<glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
<glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
<glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
<glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
<glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
<glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
<glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
<glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
<glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
<glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
<glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
<glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
<glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
<glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
<glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
<glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
<glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
<glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
<glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
<glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
<glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
<glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
<glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
<glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
<glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
<glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
<glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
<glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
<glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
<glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
<glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
<glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
<glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
<glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
<glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
<glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
<glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
<glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
<glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
<glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
<glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
<glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
<glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
<glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
<glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
<glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
<glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
<glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
<glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
<glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
<glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
<glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
<glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
<glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
<glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
<glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
<glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
<glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
<glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
<glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
<glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
<glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
<glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
<glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
<glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
<glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
<glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
<glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
<glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
<glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
<glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
<glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
<glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
<glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
<glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
<glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
<glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
<glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
<glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
<glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
<glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
<glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
<glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
<glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
<glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
<glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
<glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
<glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
<glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
<glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
<glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
<glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
<glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
<glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
<glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
<glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
<glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
<glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
<glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
<glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
<glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
<glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
<glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
<glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
<glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
<glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
<glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
<glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
<glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
<glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
<glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
<glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
<glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
<glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
<glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
<glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 106 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')

View File

@@ -0,0 +1,178 @@
div.dataTables_length label {
float: left;
text-align: left;
}
div.dataTables_length select {
width: 75px;
}
div.dataTables_filter label {
float: right;
}
div.dataTables_info {
padding-top: 8px;
}
div.dataTables_paginate {
float: right;
margin: 0;
}
table.table {
clear: both;
margin-bottom: 6px !important;
max-width: none !important;
}
table.table thead .sorting,
table.table thead .sorting_asc,
table.table thead .sorting_desc,
table.table thead .sorting_asc_disabled,
table.table thead .sorting_desc_disabled {
cursor: pointer;
*cursor: hand;
}
table.table thead .sorting { background: url('../image/sort_both.png') no-repeat center right; }
table.table thead .sorting_asc { background: url('../image/sort_asc.png') no-repeat center right; }
table.table thead .sorting_desc { background: url('../image/sort_desc.png') no-repeat center right; }
table.table thead .sorting_asc_disabled { background: url('../image/sort_asc_disabled.png') no-repeat center right; }
table.table thead .sorting_desc_disabled { background: url('../image/sort_desc_disabled.png') no-repeat center right; }
table.dataTable th:active {
outline: none;
}
/* Scrolling */
div.dataTables_scrollHead table {
margin-bottom: 0 !important;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
div.dataTables_scrollHead table thead tr:last-child th:first-child,
div.dataTables_scrollHead table thead tr:last-child td:first-child {
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.dataTables_scrollBody table {
border-top: none;
margin-bottom: 0 !important;
}
div.dataTables_scrollBody tbody tr:first-child th,
div.dataTables_scrollBody tbody tr:first-child td {
border-top: none;
}
div.dataTables_scrollFoot table {
border-top: none;
}
/*
* TableTools styles
*/
.table tbody tr.active td,
.table tbody tr.active th {
background-color: #08C;
color: white;
}
.table tbody tr.active:hover td,
.table tbody tr.active:hover th {
background-color: #0075b0 !important;
}
.table-striped tbody tr.active:nth-child(odd) td,
.table-striped tbody tr.active:nth-child(odd) th {
background-color: #017ebc;
}
table.DTTT_selectable tbody tr {
cursor: pointer;
*cursor: hand;
}
div.DTTT .btn {
color: #333 !important;
font-size: 12px;
}
div.DTTT .btn:hover {
text-decoration: none !important;
}
ul.DTTT_dropdown.dropdown-menu a {
color: #333 !important; /* needed only when demo_page.css is included */
}
ul.DTTT_dropdown.dropdown-menu li:hover a {
background-color: #0088cc;
color: white !important;
}
/* TableTools information display */
div.DTTT_print_info.modal {
height: 150px;
margin-top: -75px;
text-align: center;
}
div.DTTT_print_info h6 {
font-weight: normal;
font-size: 28px;
line-height: 28px;
margin: 1em;
}
div.DTTT_print_info p {
font-size: 14px;
line-height: 20px;
}
/*
* FixedColumns styles
*/
div.DTFC_LeftHeadWrapper table,
div.DTFC_LeftFootWrapper table,
table.DTFC_Cloned tr.even {
background-color: white;
}
div.DTFC_LeftHeadWrapper table {
margin-bottom: 0 !important;
border-top-right-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,
div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child {
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
div.DTFC_LeftBodyWrapper table {
border-top: none;
margin-bottom: 0 !important;
}
div.DTFC_LeftBodyWrapper tbody tr:first-child th,
div.DTFC_LeftBodyWrapper tbody tr:first-child td {
border-top: none;
}
div.DTFC_LeftFootWrapper table {
border-top: none;
}

View File

@@ -0,0 +1,20 @@
/***
Anout Us Page
***/
.meet-our-team h3 {
margin-bottom: 0;
padding: 0 10px 10px;
background: #fcfcfc;
}
.meet-our-team small {
display:block;
font-size:12px;
}
.meet-our-team .team-info {
padding: 10px;
overflow: hidden;
background: #fafafa;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
/***
Blog Page
***/
/*--Block Article--*/
.blog-page {
padding-bottom: 20px;
}
.blog-page h1 {
margin-bottom: 20px;
}
.blog-page h2 a {
color: #000;
}
.blog-page h2 a:hover {
color: #0d638f;
text-decoration: none;
}
.blog-page hr {
margin-top: 30px !important;
}
.blog-page .article-block {
padding-bottom: 20px;
}
.blog-page .news-img img {
margin-top: 9px;
}
.blog-page .blog-tag-data ul {
margin-bottom: 5px;
}
.blog-page .blog-tag-data li {
padding: 0;
}
.blog-page .blog-tag-data li i {
color: #78cff8;
}
.blog-page .blog-tag-data li a {
padding: 0;
color: #555;
margin-right: 8px;
}
.blog-page .blog-tag-data {
margin-bottom: 10px;
}
.blog-page .blog-tag-data ul.blog-tags a {
background: #eee;
padding: 1px 4px;
margin: 0 4px 4px 0;
display: inline-block;
}
.blog-page .blog-tag-data ul.blog-tags a:hover {
background: #ddd;
text-decoration: none;
}
.blog-page .blog-tag-data .blog-tag-data-inner {
text-align: right;
}
.blog-page .blog-tag-data img {
margin-bottom: 12px;
}
.blog-page .blog-article {
padding-bottom: 20px;
}
.blog-page .blog-article h2 {
margin-top: 0;
}
/*--Block Sidebar--*/
.blog-sidebar h2 {
font-size: 38.5px;
margin-bottom: 20px;
}
/*Twitter block*/
.blog-twitter-block {
padding: 5px;
position: relative;
margin-bottom: 10px;
border-right: solid 2px #ddd;
}
.blog-twitter-block:hover {
background: #fafafa;
border-color: #35aa47;
}
.blog-twitter-block a {
color: #4d90fe;
}
.blog-twitter-block p {
margin-bottom: 0;
}
.blog-twitter-block span {
color: #555;
display: block;
font-size: 12px;
}
.blog-twitter-block i.blog-twiiter-icon {
color: #eee;
right: 10px;
bottom: 10px;
font-size: 30px;
position: absolute;
}
/***
Blog & News Item Page
***/
/*--Media Object--*/
.blog-page .media img {
height: 54px;
position: relative;
top: 3px;
width: 54px;
}
.blog-page h4.media-heading {
position: relative;
}
.blog-page h4.media-heading span {
color: #777777;
font-size: 12px;
position: absolute;
right: 0;
top: 3px;
}
.blog-page h4.media-heading span a {
color: #78cff8;
}
/*Post Comment*/
.blog-page .post-comment .color-red {
color: #f00;
}
/*For Responsive*/
@media (max-width: 768px) {
.blog-page .blog-tag-data .blog-tag-data-inner {
text-align: left;
}
}

View File

@@ -0,0 +1,287 @@
/***
Blue theme
***/
/***
Reset and overrides
***/
body {
background-color: #1570a6 !important;
}
/***
Page header
***/
.header .navbar-inner {
filter: none !important;
background-image: none !important;
background-color: #0f4e74 !important;
}
.header .btn-navbar {
background-color: #0f4e74 !important;
}
.header .nav .dropdown-toggle:hover,
.header .nav .dropdown.open .dropdown-toggle {
background-color: #146a9d !important;
}
.header .nav li.dropdown .dropdown-toggle i {
color: #68bbec !important;
}
/***
Page sidebar
***/
.page-sidebar {
background-color: #1570a6;
}
ul.page-sidebar-menu > li > a {
border-top: 1px solid #1c95dc !important;
color: #ffffff !important;
}
ul.page-sidebar-menu > li:last-child > a {
border-bottom: 1px solid transparent !important;
}
ul.page-sidebar-menu > li a i {
color: #7fc5ef;
}
ul.page-sidebar-menu > li.open > a,
ul.page-sidebar-menu > li > a:hover,
ul.page-sidebar-menu > li:hover > a {
background: #12618f;
}
ul.page-sidebar-menu > li.active > a {
background: #cc1d1d !important;
border-top-color: transparent !important;
color: #ffffff;
}
ul.page-sidebar-menu > li.active > a i {
color: #ffffff;
}
ul.page-sidebar-menu > li > ul.sub-menu > li:first-child > a {
border-top: 0px !important;
}
ul.page-sidebar-menu > li > ul.sub-menu > li.active > a,
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
color: #ffffff !important;
background: #1b8fd3 !important;
}
ul.page-sidebar-menu > li > ul.sub-menu > li > a:hover {
background: #1b8fd3 !important;
}
/* 3rd level sub menu */
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li.active > a,
ul.page-sidebar-menu > li > ul.sub-menu li > ul.sub-menu > li > a:hover,
ul.page-sidebar-menu > li > ul.sub-menu li.open > a {
color: #ffffff !important;
background: #1b8fd3 !important;
}
/* font color for all sub menu links*/
ul.page-sidebar-menu li > ul.sub-menu > li > a {
color: #c3e4f7;
}
/* menu arrows */
ul.page-sidebar-menu > li > a .arrow:before,
ul.page-sidebar-menu > li > a .arrow.open:before {
color: #51b1e9 !important;
}
ul.page-sidebar-menu > li > ul.sub-menu a .arrow:before,
ul.page-sidebar-menu > li > ul.sub-menu a .arrow.open:before {
color: #3ba6e6 !important;
}
ul.page-sidebar-menu > li > a > .arrow.open:before {
color: #68bbec !important;
}
ul.page-sidebar-menu > li.active > a .arrow:before,
ul.page-sidebar-menu > li.active > a .arrow.open:before {
color: #ffffff !important;
}
/* sidebar search */
.page-sidebar .sidebar-search input {
background-color: #0f5179 !important;
color: #51b1e9;
}
.page-sidebar .sidebar-search input::-webkit-input-placeholder {
color: #51b1e9 !important;
}
.page-sidebar .sidebar-search input:-moz-placeholder {
color: #51b1e9 !important;
}
.page-sidebar .sidebar-search input:-ms-input-placeholder {
color: #51b1e9 !important;
}
.page-sidebar .sidebar-search input {
background-color: #1570a6 !important;
color: #bfbfbf !important;
}
.page-sidebar .sidebar-search .input-box {
border-bottom: 1px solid #51b1e9 !important;
}
.page-sidebar .sidebar-search .submit {
background-image: url(../../img/search-icon-blue.png);
}
/***
Sidebar toggler
***/
.sidebar-toggler {
background-image: url(../../img/sidebar-toggler-blue.jpg);
background-color: #0f5179;
}
/* search box bg color on expanded */
.page-sidebar-closed .page-sidebar .sidebar-search.open {
background-color: #1570a6 !important;
}
.page-sidebar-closed .page-sidebar .sidebar-search.open .remove {
background-image: url("../../img/sidebar-search-close-blue.png");
}
/* sub menu bg color on hover menu item */
.page-sidebar-closed ul.page-sidebar-menu > li:hover .sub-menu {
background-color: #1570a6;
}
/***
Horizontal Menu(new in v1.2)
***/
/*search*/
.header .hor-menu .hor-menu-search-form-toggler.hide {
background: #000000 url(../../img/hor-menu-search-close.png) no-repeat center;
}
.header .hor-menu .search-form {
background: #000000;
}
.header .hor-menu .search-form .btn {
color: #f0f8fd;
background: #04141e url(../../img/search-icon.png) no-repeat center;
}
.header .hor-menu .search-form form input {
color: #f0f8fd;
}
.header .hor-menu .search-form form input::-webkit-input-placeholder {
/* WebKit browsers */
color: #f0f8fd;
}
.header .hor-menu .search-form form input:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #f0f8fd;
}
.header .hor-menu .search-form form input::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #f0f8fd;
}
.header .hor-menu .search-form form input:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #f0f8fd;
}
/***
Footer
***/
.footer .footer-inner {
color: #68bbec;
}
.footer .footer-tools .go-top {
background-color: #1985c6;
}
.footer .footer-tools .go-top:hover {
opacity: 0.7;
filter: alpha(opacity=70);
}
.footer .footer-tools .go-top i {
color: #68bbec;
}
/***
Footer Layouts (new in v1.3)
***/
/* begin:fixed footer */
.page-footer-fixed .footer {
background-color: #0f5179;
}
.page-footer-fixed .footer .footer-inner {
color: #68bbec;
}
.page-footer-fixed .footer .footer-tools .go-top {
background-color: #1985c6;
}
.page-footer-fixed .footer .footer-tools .go-top i {
color: #68bbec;
}
/* end:fixed footer */
/***
Gritter Notifications
***/
.gritter-top {
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -30px !important;
}
.gritter-bottom {
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left bottom !important;
}
.gritter-item {
display: block;
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left -40px !important;
}
.gritter-close {
background: url(../../plugins/gritter/images/gritter-blue.png) no-repeat left top !important;
}
.gritter-title {
text-shadow: none !important;
/* Not supported by IE :( */
}
/* for the light (white) version of the gritter notice */
.gritter-light .gritter-item,
.gritter-light .gritter-bottom,
.gritter-light .gritter-top,
.gritter-light .gritter-close {
background-image: url(../../plugins/gritter/images/gritter-light.png) !important;
}
.gritter-item-wrapper a {
color: #18a5ed;
}
.gritter-item-wrapper a:hover {
color: #0b6694;
}
/* begin: boxed page */
@media (min-width: 980px) {
.page-boxed {
background-color: #125e8b !important;
}
.page-boxed .page-container {
background-color: #1570a6;
border-left: 1px solid #1c98e1;
border-bottom: 1px solid #1c98e1;
}
.page-boxed.page-sidebar-fixed .page-container {
border-left: 0;
border-bottom: 0;
}
.page-boxed.page-sidebar-fixed .page-sidebar {
border-left: 1px solid #1c98e1;
}
.page-boxed.page-sidebar-fixed.page-footer-fixed .footer {
background-color: #125e8b !important;
}
}
/* end: boxed page */
/***
Landscape phone to portrait tablet
***/
@media (max-width: 979px) {
/***
page sidebar
***/
.page-sidebar {
background-color: #105882 !important;
}
ul.page-sidebar-menu > li > a {
border-top: 1px solid #187fbd !important;
}
ul.page-sidebar-menu > li:last-child > a {
border-bottom: 0 !important;
}
.page-sidebar .sidebar-search input {
background-color: #105882 !important;
}
ul.page-sidebar-menu > li.open > a,
ul.page-sidebar-menu > li > a:hover,
ul.page-sidebar-menu > li:hover > a {
background: #0e4b70;
}
}

View File

@@ -0,0 +1,238 @@
/*!
* Datetimepicker for Bootstrap v3
//! version : 3.1.3
* https://github.com/Eonasdan/bootstrap-datetimepicker/
*/
.bootstrap-datetimepicker-widget {
top: 0;
left: 0;
width: 250px;
padding: 4px;
margin-top: 1px;
z-index: 99999 !important;
border-radius: 4px;
}
.bootstrap-datetimepicker-widget.timepicker-sbs {
width: 600px;
}
.bootstrap-datetimepicker-widget.bottom:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-bottom-color: rgba(0, 0, 0, 0.2);
position: absolute;
top: -7px;
left: 7px;
}
.bootstrap-datetimepicker-widget.bottom:after {
content: '';
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
position: absolute;
top: -6px;
left: 8px;
}
.bootstrap-datetimepicker-widget.top:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-top: 7px solid #ccc;
border-top-color: rgba(0, 0, 0, 0.2);
position: absolute;
bottom: -7px;
left: 6px;
}
.bootstrap-datetimepicker-widget.top:after {
content: '';
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid white;
position: absolute;
bottom: -6px;
left: 7px;
}
.bootstrap-datetimepicker-widget .dow {
width: 14.2857%;
}
.bootstrap-datetimepicker-widget.pull-right:before {
left: auto;
right: 6px;
}
.bootstrap-datetimepicker-widget.pull-right:after {
left: auto;
right: 7px;
}
.bootstrap-datetimepicker-widget > ul {
list-style-type: none;
margin: 0;
}
.bootstrap-datetimepicker-widget a[data-action] {
padding: 6px 0;
}
.bootstrap-datetimepicker-widget a[data-action]:active {
box-shadow: none;
}
.bootstrap-datetimepicker-widget .timepicker-hour,
.bootstrap-datetimepicker-widget .timepicker-minute,
.bootstrap-datetimepicker-widget .timepicker-second {
width: 54px;
font-weight: bold;
font-size: 1.2em;
margin: 0;
}
.bootstrap-datetimepicker-widget button[data-action] {
padding: 6px;
}
.bootstrap-datetimepicker-widget table[data-hour-format="12"] .separator {
width: 4px;
padding: 0;
margin: 0;
}
.bootstrap-datetimepicker-widget .datepicker > div {
display: none;
}
.bootstrap-datetimepicker-widget .picker-switch {
text-align: center;
}
.bootstrap-datetimepicker-widget table {
width: 100%;
margin: 0;
}
.bootstrap-datetimepicker-widget td,
.bootstrap-datetimepicker-widget th {
text-align: center;
border-radius: 4px;
}
.bootstrap-datetimepicker-widget td {
height: 54px;
line-height: 54px;
width: 54px;
}
.bootstrap-datetimepicker-widget td.cw {
font-size: 10px;
height: 20px;
line-height: 20px;
color: #777777;
}
.bootstrap-datetimepicker-widget td.day {
height: 20px;
line-height: 20px;
width: 20px;
}
.bootstrap-datetimepicker-widget td.day:hover,
.bootstrap-datetimepicker-widget td.hour:hover,
.bootstrap-datetimepicker-widget td.minute:hover,
.bootstrap-datetimepicker-widget td.second:hover {
background: #eeeeee;
cursor: pointer;
}
.bootstrap-datetimepicker-widget td.old,
.bootstrap-datetimepicker-widget td.new {
color: #777777;
}
.bootstrap-datetimepicker-widget td.today {
position: relative;
}
.bootstrap-datetimepicker-widget td.today:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-bottom: 7px solid #428bca;
border-top-color: rgba(0, 0, 0, 0.2);
position: absolute;
bottom: 4px;
right: 4px;
}
.bootstrap-datetimepicker-widget td.active,
.bootstrap-datetimepicker-widget td.active:hover {
background-color: #428bca;
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget td.active.today:before {
border-bottom-color: #fff;
}
.bootstrap-datetimepicker-widget td.disabled,
.bootstrap-datetimepicker-widget td.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget td span {
display: inline-block;
width: 54px;
height: 54px;
line-height: 54px;
margin: 2px 1.5px;
cursor: pointer;
border-radius: 4px;
}
.bootstrap-datetimepicker-widget td span:hover {
background: #eeeeee;
}
.bootstrap-datetimepicker-widget td span.active {
background-color: #428bca;
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget td span.old {
color: #777777;
}
.bootstrap-datetimepicker-widget td span.disabled,
.bootstrap-datetimepicker-widget td span.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget th {
height: 20px;
line-height: 20px;
width: 20px;
}
.bootstrap-datetimepicker-widget th.picker-switch {
width: 145px;
}
.bootstrap-datetimepicker-widget th.next,
.bootstrap-datetimepicker-widget th.prev {
font-size: 21px;
}
.bootstrap-datetimepicker-widget th.disabled,
.bootstrap-datetimepicker-widget th.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget thead tr:first-child th {
cursor: pointer;
}
.bootstrap-datetimepicker-widget thead tr:first-child th:hover {
background: #eeeeee;
}
.input-group.date .input-group-addon span {
display: block;
cursor: pointer;
width: 16px;
height: 16px;
}
.bootstrap-datetimepicker-widget.left-oriented:before {
left: auto;
right: 6px;
}
.bootstrap-datetimepicker-widget.left-oriented:after {
left: auto;
right: 7px;
}
.bootstrap-datetimepicker-widget ul.list-unstyled li div.timepicker div.timepicker-picker table.table-condensed tbody > tr > td {
padding: 0px !important;
}
@media screen and (max-width: 767px) {
.bootstrap-datetimepicker-widget.timepicker-sbs {
width: 283px;
}
}

View File

@@ -0,0 +1,116 @@
.btn-file {
position: relative;
overflow: hidden;
vertical-align: middle;
}
.btn-file > input {
position: absolute;
top: 0;
right: 0;
margin: 0;
font-size: 23px;
cursor: pointer;
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
direction: ltr;
}
.fileupload {
margin-bottom: 9px;
}
.fileupload .uneditable-input {
display: inline-block;
margin-bottom: 0;
vertical-align: middle;
cursor: text;
}
.fileupload .thumbnail {
display: inline-block;
margin-bottom: 5px;
overflow: hidden;
text-align: center;
vertical-align: middle;
}
.fileupload .thumbnail > img {
display: inline-block;
max-height: 100%;
vertical-align: middle;
}
.fileupload .btn {
vertical-align: middle;
}
.fileupload-exists .fileupload-new,
.fileupload-new .fileupload-exists {
display: none;
}
.fileupload-inline .fileupload-controls {
display: inline;
}
.fileupload-new .input-append .btn-file {
-webkit-border-radius: 0 3px 3px 0;
-moz-border-radius: 0 3px 3px 0;
border-radius: 0 3px 3px 0;
}
.thumbnail-borderless .thumbnail {
padding: 0;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.fileupload-new.thumbnail-borderless .thumbnail {
border: 1px solid #ddd;
}
.control-group.warning .fileupload .uneditable-input {
color: #a47e3c;
border-color: #a47e3c;
}
.control-group.warning .fileupload .fileupload-preview {
color: #a47e3c;
}
.control-group.warning .fileupload .thumbnail {
border-color: #a47e3c;
}
.control-group.error .fileupload .uneditable-input {
color: #b94a48;
border-color: #b94a48;
}
.control-group.error .fileupload .fileupload-preview {
color: #b94a48;
}
.control-group.error .fileupload .thumbnail {
border-color: #b94a48;
}
.control-group.success .fileupload .uneditable-input {
color: #468847;
border-color: #468847;
}
.control-group.success .fileupload .fileupload-preview {
color: #468847;
}
.control-group.success .fileupload .thumbnail {
border-color: #468847;
}

View File

@@ -0,0 +1,214 @@
/*!
* Bootstrap Modal
*
* Copyright Jordan Schroter
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
*/
.modal-open {
overflow: hidden;
}
/* add a scroll bar to stop page from jerking around */
.modal-open.page-overflow .page-container,
.modal-open.page-overflow .page-container .navbar-fixed-top,
.modal-open.page-overflow .page-container .navbar-fixed-bottom,
.modal-open.page-overflow .modal-scrollable {
overflow-y: scroll;
}
@media (max-width: 979px) {
.modal-open.page-overflow .page-container .navbar-fixed-top,
.modal-open.page-overflow .page-container .navbar-fixed-bottom {
overflow-y: visible;
}
}
.modal-scrollable {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
}
.modal {
outline: none;
position: absolute;
margin-top: 0;
top: 50%;
overflow: visible; /* allow content to popup out (i.e tooltips) */
}
.modal.fade {
top: -100%;
-webkit-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
-moz-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
-o-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
}
.modal.fade.in {
top: 50%;
}
.modal-body {
max-height: none;
overflow: visible;
}
.modal.modal-absolute {
position: absolute;
z-index: 950;
}
.modal .loading-mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #fff;
border-radius: 6px;
}
.modal-backdrop.modal-absolute{
position: absolute;
z-index: 940;
}
.modal-backdrop,
.modal-backdrop.fade.in{
opacity: 0.7;
filter: alpha(opacity=70);
background: #fff;
}
.modal.container {
width: 940px;
margin-left: -470px;
}
/* Modal Overflow */
.modal-overflow.modal {
top: 1%;
}
.modal-overflow.modal.fade {
top: -100%;
}
.modal-overflow.modal.fade.in {
top: 1%;
}
.modal-overflow .modal-body {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
/* Responsive */
@media (min-width: 1200px) {
.modal.container {
width: 1170px;
margin-left: -585px;
}
}
@media (max-width: 979px) {
.modal,
.modal.container,
.modal.modal-overflow {
top: 1%;
right: 1%;
left: 1%;
bottom: auto;
width: auto !important;
height: auto !important;
margin: 0 !important;
padding: 0 !important;
}
.modal.fade.in,
.modal.container.fade.in,
.modal.modal-overflow.fade.in {
top: 1%;
bottom: auto;
}
.modal-body,
.modal-overflow .modal-body {
position: static;
margin: 0;
height: auto !important;
max-height: none !important;
overflow: visible !important;
}
.modal-footer,
.modal-overflow .modal-footer {
position: static;
}
}
.loading-spinner {
position: absolute;
top: 50%;
left: 50%;
margin: -12px 0 0 -12px;
}
/*
Animate.css - http://daneden.me/animate
Licensed under the ☺ license (http://licence.visualidiot.com/)
Copyright (c) 2012 Dan Eden*/
.animated {
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
}
@-webkit-keyframes shake {
0%, 100% {-webkit-transform: translateX(0);}
10%, 30%, 50%, 70%, 90% {-webkit-transform: translateX(-10px);}
20%, 40%, 60%, 80% {-webkit-transform: translateX(10px);}
}
@-moz-keyframes shake {
0%, 100% {-moz-transform: translateX(0);}
10%, 30%, 50%, 70%, 90% {-moz-transform: translateX(-10px);}
20%, 40%, 60%, 80% {-moz-transform: translateX(10px);}
}
@-o-keyframes shake {
0%, 100% {-o-transform: translateX(0);}
10%, 30%, 50%, 70%, 90% {-o-transform: translateX(-10px);}
20%, 40%, 60%, 80% {-o-transform: translateX(10px);}
}
@keyframes shake {
0%, 100% {transform: translateX(0);}
10%, 30%, 50%, 70%, 90% {transform: translateX(-10px);}
20%, 40%, 60%, 80% {transform: translateX(10px);}
}
.shake {
-webkit-animation-name: shake;
-moz-animation-name: shake;
-o-animation-name: shake;
animation-name: shake;
}

Some files were not shown because too many files have changed in this diff Show More