get ldap attribute PwdLastSet using java - java

I am trying to retrieve the PwdLastSet attribute from LDAP using java. It fails and doesn't throw an error. Here's the code:
private String getPasswordLastSet() {
int searchScope = LDAPConnection.SCOPE_BASE;
int ldapVersion = LDAPConnection.LDAP_V3;
int ldapPort = 389;
String ldapHost = "Adapps.domain.mycompany.com";
String loginDN = "cn=myNTusername,OU=users,OU=colorado,OU=corporate,dc=domain,dc=mycompany,dc=com";
String password = "myNTpassword";
String baseDn = "dc=mycompany,dc=com";
LDAPConnection lc = new LDAPConnection();
String attributes[] = {"PwdLastSet"};
String pwdLastSet = null;
try {
lc.connect( ldapHost, ldapPort );
lc.bind( ldapVersion, loginDN, password.getBytes("UTF8") );
String filter = "(sAMAccountName=myNtusername)";
LDAPSearchResults searchResults =
lc.search( baseDn,
searchScope,
filter,
attributes,
true); // return attributes and values
while ( searchResults.hasMore()) {
LDAPEntry nextEntry = null;
try {
actionlogger.debug("about to searchResults.next...");
nextEntry = searchResults.next();
actionlogger.debug("about to nextEntry.getAttribute...");
LDAPAttribute pwdLastSetAttribute = nextEntry.getAttribute("PwdLastSet");
pwdLastSet = pwdLastSetAttribute.getStringValue();
} catch(LDAPException e) {
e.printStackTrace();
} catch(Exception e){
e.printStackTrace();
}
}
} catch( LDAPException e ) {
actionlogger.error( "Error occured while LDAP Search : " + e.getMessage(),e );
} catch (Exception e) {
e.printStackTrace();
}
return pwdLastSet;
}
The output is
about to searchResults.next...
But
about to nextEntry.getAttribute...
is never hit. Any ideas?

It was nearly correct. I just
Changed searchScope to LDAPConnection.SCOPE_SUB;
Changed loginDN = DOMAIN\MyNTusername;
Changed baseDN = "dc=mydomain,dc=mycompany,dc=com";
Changed true to false in lc.search.
Not sure which of those changes caused it to start working.

Related

How to get value of a cell by column name in java using azure-kusto-java library

public KustoResultSetTable executeKustoQuery(ClientImpl client, String query) {
KustoResultSetTable mainTableResult = null;
try {
KustoOperationResult results = client.execute(databaseName, query);
mainTableResult = results.getPrimaryResults();
} catch (DataServiceException | DataClientException e) {
errorHandler(e, "Error while retrieving results from kusto query!");
}
return mainTableResult;
}
The above code returns me a result of this type
Name | Age
XYZ AAA | 29
How can I get the value of 1st row under name column using Azure Kusto Java mainTableResult object
Expected String output - "XYZ AAA"
You can do:
if (mainTableResult.first()) {
int columnIndex = mainTableResult.findColumn("Name")
return mainTableResult.getString(columnIndex);
} else {
throw new UnsupportedOperationException(""); // Or any other error handling
}
A complete version is:
public String executeKustoQuery(ClientImpl client, String query) {
KustoResultSetTable mainTableResult = null;
try {
KustoOperationResult results = client.execute("databaseName", query);
mainTableResult = results.getPrimaryResults();
if (mainTableResult.first()) {
int columnIndex = mainTableResult.findColumn("Name")
return mainTableResult.getString(columnIndex);
} else {
throw new UnsupportedOperationException(""); // Or any other error handling
}
} catch (DataServiceException | DataClientException e) {
errorHandler(e, "Error while retrieving results from kusto query!");
}
}

Google-Reflections : When should reflections library be used? and How to create dynamic POJO from table metadata?

I am a hibernate learner. I have came to know about google-reflections library when I was researching on how to make dynamic POJO class when Only Table and schema name is provided i.e.
try {
sessionFactory = new StringUtil().getSessionFactory(className);
session = sessionFactory.openSession();
sessionImp = (SessionImpl) session;
System.out.println("Product name ["
+ sessionImp.connection().getMetaData()
.getDatabaseProductName() + "] table name "+tableName);
metadata = sessionImp.connection().getMetaData();
tables = metadata.getTables(null, "SDP", null,
new String[] { "TABLE" });
// tables = metadata.getTables( null, "public", null, new
// String[]{"TABLE"} );//Postgres
ResultSet rs = metadata.getExportedKeys("SDP", "SDP", tableName);
while (rs.next()) {
PojoGenerator.pkey = rs.getString("PKCOLUMN_NAME");
}
System.out.println("Primary key of Table is ["+PojoGenerator.pkey+"]");
while (tables.next()) {
tName = tables.getString(3);
if (tName.equalsIgnoreCase(tableName)) {
columns = metadata.getColumns("SDP", "SDP", tName, null);
// columns = metadata.getColumns("sdp", "public", tName,
// null);//Postgres
while (columns.next()) {
tableMetadata = new TableMetadata();
tableMetadata.setColumnName(columns.getString("COLUMN_NAME"));
tableMetadata.setPropertyName(new StringUtil().getWordCaseNames(columns.getString("COLUMN_NAME")));
//tableMetadata.setRealColumnName( columns.getString("COLUMN_NAME") );
tableMetadata.setColumnType(new StringUtil().dbToJavaDataType(
columns.getString("TYPE_NAME"),
columns.getInt("COLUMN_SIZE"),
columns.getString("DECIMAL_DIGITS")));
tableMetadata.setColumnLength(columns.getInt("COLUMN_SIZE"));
tableMetadata.setSession(session);
list.add(tableMetadata);
}
columns = null;
tName = null;
}
}
} catch (Exception e) {
e.printStackTrace();
}
This metadata helped me to generate POJO:
public static Class generate(String className, Map<String, Class<?>> properties, List tableDetails) throws NotFoundException, CannotCompileException {
boolean needToCreateClass = false;
Object obj = null;
Class<?> clazz = null;
CtMethod getterMethod = null;
TableMetadata tableMetadata = null;
int numberOfColumnsInTable = 0;
try {
clazz = Class.forName(className);
obj = clazz.newInstance();
if ( obj != null ){
needToCreateClass = false;
}else{
needToCreateClass = true;
}
}catch (Exception e){
needToCreateClass = true;
}
System.out.println("Need to create a class ["+needToCreateClass+"]");
if ( needToCreateClass ) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
// add this to define a super class to extend
// cc.setSuperclass(resolveCtClass(MySuperClass.class));
// add this to define an interface to implement
cc.addInterface(resolveCtClass(Serializable.class));
ClassFile cf = cc.getClassFile();
ConstPool constpool = cf.getConstPool();
AnnotationsAttribute attrTable = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
AnnotationsAttribute attrColumn = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation [] tableAnnotations = new Annotation[]{new Annotation("javax.persistence.Entity", constpool), new Annotation("javax.persistence.Table", constpool) };
for (Entry<String, Class<?>> entry : properties.entrySet()) {
cc.addField(new CtField(resolveCtClass(entry.getValue()), entry.getKey(), cc));
// System.out.println("Key is ["+entry.getKey()+"]");
getterMethod = generateGetter(cc, entry.getKey(), entry.getValue());
// add getter
cc.addMethod(getterMethod);
if ( numberOfColumnsInTable == 0 ) {
tableAnnotations[1].addMemberValue("name", new StringMemberValue("CRBT_RBT", constpool));
tableAnnotations[1].addMemberValue("schema", new StringMemberValue("SDP", constpool));
attrTable.setAnnotations(tableAnnotations);
cc.getClassFile().addAttribute(attrTable);
attrTable = null;
}
attrColumn = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation annot1[] = {new Annotation("javax.persistence.Id", constpool),new Annotation("javax.persistence.Column", constpool)};
Annotation annot2[] = {new Annotation("javax.persistence.Column", constpool)};
tableMetadata = (TableMetadata)tableDetails.get( numberOfColumnsInTable );
if ( numberOfColumnsInTable < tableDetails.size() ) {
String realColumnName=new StringUtil().getRealName( entry.getKey());
if(realColumnName.equalsIgnoreCase(pkey)){
annot1[1].addMemberValue("name", new StringMemberValue( realColumnName , constpool ) );
attrColumn.setAnnotations(annot1);
}else{
annot2[0].addMemberValue("name", new StringMemberValue( realColumnName , constpool ) );
attrColumn.setAnnotations(annot2);
}
numberOfColumnsInTable++;
}
getterMethod.getMethodInfo().addAttribute(attrColumn);
// add setter
cc.addMethod(generateSetter(cc, entry.getKey(), entry.getValue()));
}
try {
cc.writeFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
Validation for applied annotations
*/
try {
Object[] all = cc.getAnnotations();
int k = 0;
for (Object object : all) {
System.out.println(all[k]);
k++;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
/* Validation End */
return cc.toClass();
}else{
return clazz;
}
}
but now I need to map those Dynamically created POJO with hibernate configuration. So my question comes here:
1. Can I use reflections library for that?
2. How?
3. If not, Is there any Other solutions besides creating .hbm.xml files for each class?
please help. Thanks in advance.
UPDATE :
I have an Idea but I don't know how it will work.
Idea:
I will create .hbm.xml files for each class dynamically and will map the package of those classes in hibernate.cfg.xml.
But
1.I don't know How to scan the mapping file by package mapping.
2. I don't even know if it is possible or not and if possible then how?

PreparedStatement error: At least one parameter to the current statement is uninitialized

I am not able to find out why my executeUpdate() statement is returning this exception: "At least one parameter to the current statement is uninitialized". Can anyone spot what I am doing wrong? (I am aware that there are excessive try/catches in the code)
public class MetadataRetriever2 extends SwingWorker<MediaMeta, MediaMeta> {
private final List<File> dataFlavorFileList;
private final DefaultTableModel activeModel;
private static MediaMeta trackMetaData;
private static final MediaPlayerFactory factory = new MediaPlayerFactory();
int row = 0;
private int dropLocationRow;
Connection connection = null;
PreparedStatement myPreparedStatement = null;
EmbeddedDataSource dataSource = null;
MetadataRetriever2(List dataFlavorFileList, DefaultTableModel activeModel, int dropLocationRow) {
this.dropLocationRow = dropLocationRow;
this.dataFlavorFileList = dataFlavorFileList;
this.activeModel = activeModel;
}
#Override
protected MediaMeta doInBackground() throws Exception {
for (File file : dataFlavorFileList) {
if (MediaFileFilter.INSTANCE.accept(file)) {
trackMetaData = factory.getMediaMeta(file.toPath().toString(), true);
} else {
}
publish(trackMetaData);
}
return trackMetaData;
}
#Override
protected void process(List<MediaMeta> trackMetaData) {
String sql = "INSERT INTO DEFAULT_LIBRARY (ARTIST, TITLE, ALBUM, TRACK_NUMBER, LENGTH, "
+ "DESCRIPTION, RATING,DATE ,SETTING, URL, LANGUAGE, NOW_PLAYING, PUBLISHER, ENCODED_BY,"
+ "ARTWORK_URL, TRACK_ID) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
dataSource = new EmbeddedDataSource();
dataSource.setDatabaseName("audioPlayerDB");
try {
connection = dataSource.getConnection();
} catch (SQLException ex) {
System.out.println("connection failed");
}
try {
myPreparedStatement = connection.prepareStatement(sql);
} catch (SQLException ex) {
System.out.println("preparedStatement failed: " + ex.getCause());
}
String[] oArray = new String[16];
for (MediaMeta trackData : trackMetaData) {
oArray[0] = trackData.getArtist();
oArray[1] = trackData.getTitle();
oArray[2] = trackData.getAlbum();
oArray[3] = trackData.getTrackNumber();
oArray[4] = String.valueOf(trackData.getLength());
oArray[5] = trackData.getDescription();
oArray[6] = trackData.getRating();
oArray[7] = trackData.getDate();
oArray[8] = trackData.getSetting();
oArray[9] = trackData.getUrl();
oArray[10] = trackData.getLanguage();
oArray[11] = trackData.getNowPlaying();
oArray[12] = trackData.getPublisher();
oArray[13] = trackData.getEncodedBy();
oArray[14] = trackData.getArtworkUrl();
oArray[15] = trackData.getTrackId();
try {
myPreparedStatement.setString(1, oArray[0]);
myPreparedStatement.setString(2, oArray[1]);
myPreparedStatement.setString(3, oArray[2]);
myPreparedStatement.setString(4, oArray[3]);
myPreparedStatement.setString(5, oArray[4]);
myPreparedStatement.setString(6, oArray[5]);
myPreparedStatement.setString(7, oArray[6]);
myPreparedStatement.setString(8, oArray[7]);
myPreparedStatement.setString(9, oArray[8]);
myPreparedStatement.setString(10, oArray[9]);
myPreparedStatement.setString(11, oArray[10]);
myPreparedStatement.setString(12, oArray[11]);
myPreparedStatement.setString(13, oArray[12]);
myPreparedStatement.setString(14, oArray[13]);
myPreparedStatement.setString(15, oArray[15]);
activeModel.insertRow(dropLocationRow, oArray);
dropLocationRow++;
} catch (SQLException ex) {
Logger.getLogger(MetadataRetriever2.class.getName()).log(Level.SEVERE, null, ex);
}
try {
myPreparedStatement.executeUpdate();
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
}
Your statement requires 16 parameters, and your object[] doesn't line up
myPreparedStatement.setString(14, oArray[13]);
myPreparedStatement.setString(15, oArray[15]);
should be
myPreparedStatement.setString(14, oArray[13]);
myPreparedStatement.setString(15, oArray[14]);
myPreparedStatement.setString(16, oArray[15]);

how to fix path manipulation and null deference issues for the following sample

I am getting the following issues after scanning the code using fortify....
1>path manipulation issue:
private MimeMessage prepareMessage(EmailMessage req) throws EmailProviderException {
long start=System.currentTimeMillis(),finish=0;
try {
MimeMessage message = emailSender.createMimeMessage();
// Create a multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// Set email addresses
helper.setFrom(convertAddress(req.getFromAddress()));
helper.setTo(convertAddress(req.getToAddress()));
helper.setCc(convertAddress(req.getCcAddress()));
helper.setBcc(convertAddress(req.getBccAddress()));
// Set subject and body
helper.setSubject(req.getEmailSubject());
String emailBody = req.getEmailBody();
String emailMime = req.getEmailMimeType();
MimeBodyPart messagePart = new MimeBodyPart();
DataSource bodyDataSource = new ByteArrayDataSource(emailBody, emailMime);
messagePart.setDataHandler(new DataHandler(bodyDataSource));
helper.getMimeMultipart().addBodyPart(messagePart);
// Add attachments
List<EmailAttachment> lAttach = req.getEmailAttachment();
if (lAttach != null) {
for (EmailAttachment attachMnt: lAttach) {
DataSource dSource = new ByteArrayDataSource(attachMnt
.getContent(), attachMnt
.getMimeType());
helper.addAttachment(attachMnt.getFileName(), dSource);
}
}
finish=System.currentTimeMillis();
statsLogger.info(new FedExLogEntry("prepareMessage took {0}ms",new Object[]{finish-start}));
return message;
} catch (Exception e) {
// Covers MessagingException, IllegalStateException, IOException, MailException
String emsg = new StringBuilder("Unable to prepare smtp message.")
.append("\n").append(req.toString()).toString();
logger.warn(emsg, e);
throw new EmailProviderException(emsg, e);
}
}
Null dereference issues
issue 1.
public byte[] toByteArray(Notification nd) throws EmailProviderException {
String message = null;
try {
JAXBContext jc = JAXBContext.newInstance(nd.getClass());
if (jc != null) {
Marshaller m = jc.createMarshaller();
StringWriter sw = new StringWriter();
m.marshal(nd, sw);
message = sw.toString();
}
} catch (JAXBException e) {
throw new EmailProviderException("Unable to convert NDS notification to byte array.", e);
}
return message.getBytes();
}
null dereference issue 2..
private void addLastUpdatedHours(
List<LocationHoursForADate> masterHours, List<LocationHoursWithSearchedDate> hoursToAdd, Map<String,String> scheduleTypeIncludesMap){
String prevScheduleTypeCode = null;
String prevHourTypeCode = null;
Date searchedDate = null;
// Build map of locationHours to searchDates
List<LocationHours> locationHours = null;
Map<Date, List<LocationHours>> locationHoursSearchDatesMap = new HashMap<Date, List<LocationHours>>();
for(LocationHoursWithSearchedDate locationHoursWithSearchedDate : hoursToAdd) {
if(scheduleTypeIncludesMap.containsKey(locationHoursWithSearchedDate.getLocationHoursPK().getScheduleTypeCd())) {
searchedDate = locationHoursWithSearchedDate.getLocationHoursPK().getSearchedDate();
locationHours = locationHoursSearchDatesMap.get(searchedDate);
if(locationHours==null) {
locationHours = new ArrayList<LocationHours>();
locationHoursSearchDatesMap.put(searchedDate,locationHours);
}
locationHours.add(locationHoursWithSearchedDate.createLocationHours());
}
}
for(Map.Entry<Date,List<LocationHours>> entry : locationHoursSearchDatesMap.entrySet()) {
prevHourTypeCode = null;
prevScheduleTypeCode = null;
searchedDate = entry.getKey();
for(LocationHours hour: entry.getValue()){
// new ST & new 01, add it
if((prevScheduleTypeCode == null) && (prevHourTypeCode == null)){
masterHours.add(new LocationHoursForADate(searchedDate, hour));
prevScheduleTypeCode = hour.getLocationHoursPK().getScheduleTypeCd();
prevHourTypeCode = hour.getLocationHoursPK().getHoursTypeCd();
}
else{
//same ST
if(prevScheduleTypeCode.equals(hour.getLocationHoursPK().getScheduleTypeCd())){
// same 01, skip this schedule
if(prevHourTypeCode.equals(hour.getHoursType().getHoursTypeCd())){
continue;
}
else { //new 01, add it
masterHours.add(new LocationHoursForADate(searchedDate, hour));
prevScheduleTypeCode = hour.getLocationHoursPK().getScheduleTypeCd();
prevHourTypeCode = hour.getLocationHoursPK().getHoursTypeCd();
}
}
else{ //new ST, add it
masterHours.add(new LocationHoursForADate(searchedDate, hour));
prevScheduleTypeCode = hour.getLocationHoursPK().getScheduleTypeCd();
prevHourTypeCode = hour.getLocationHoursPK().getHoursTypeCd();
}
}
}
}
}
}
Well, the second case (null deference 1) is easy to spot.
The problem is that if there is an exception in the try-catch block then the object message will be null, so the final instruction return message.getBytes() will raise a NullPointerException.
One way to avoid it is changing the return statement like this:
return message != null ? message.getBytes() : null;
But maybe, you will prefer to raise the exception...

The functionalities are working locally, but once I host this message display for some of the pages

The functions are working locally, but once I host this message display for some of the pages
java.sql.SQLException: Access denied for user 'myshelf'#'54.235.58.92' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1056)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3376)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3308)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:894)
at com.mysql.jdbc.MysqlIO.secureAuth411(MysqlIO.java:3808)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1256)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2032)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:729)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
at sun.reflect.GeneratedConstructorAccessor71.newInstance(Unknown Source
i am trying to create a new catalog and add the picture of the cover to S3 bucket
String awsAccessKey = "";
String awsSecretKey = "";
String name_val="";
String desc_val="";
// HttpSession session = request.getSession(true);
//String username = (String) session.getAttribute("user_session");
//String clubfield=(String) session.getAttribute("res_ses");*/
// int att_id=0;
//String[] ccode;
String fieldname ="",fieldvalue="",fieldname1="" ,fieldvalue2="",fieldname2="",fieldvalue1="" ,fieldvalue3="",fieldname3="";
String categori="" ;
String category="" ;
String catalog="" ;
String nb="" ;
// String cclub="";
Connection con = null;
// ccode = clubfield.split("-");
// cclub=ccode[0];
String filetit="";
String filename="";
String test="";
int s=0;
// System.out.println("club code"+cclub);
try{
AWSCredentials awsCredentials =
new AWSCredentials(awsAccessKey, awsSecretKey);
S3Service s3Service = new RestS3Service(awsCredentials);
S3Bucket[] myBuckets = s3Service.listAllBuckets();
System.out.println("How many buckets to I have in S3? " + myBuckets.length);
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) {
fieldname = item.getFieldName();
if(fieldname.equals("catalog")){
name_val=item.getString();
}
if(fieldname.equals("catalog")){
catalog=item.getString();
System.out.println(catalog);
}
if(fieldname.equals("desc")){
desc_val=item.getString();
}
if(fieldname.equals("cat")){
category=item.getString();
System.out.println(category);
}
if(fieldname.equals("nb")){
nb=item.getString();
System.out.println(nb);
}
fieldvalue = item.getString();
fieldname1 = item.getFieldName();
System.out.println("fieldname1"+fieldname1);
fieldvalue1 = item.getString();
fieldname2 = item.getFieldName();
fieldvalue2 = item.getString();
System.out.println("fieldname1"+ fieldvalue);
System.out.println("fieldname"+fieldname+ "--"+fieldvalue);
System.out.println(fieldname1+ "--"+fieldvalue1);
System.out.println(fieldname3+ "--"+fieldvalue3);
filetit=fieldvalue+"/"+filename;
} else {
// Process form file field (input type="file").
filename = FilenameUtils.getName(item.getName());
System.out.println("filename come on come on--"+filename);
if(!filename.equals(""))
{ InputStream filecontent = item.getInputStream();
// System.out.println(att_id+"/"+cclub+"_clubcode.jpg");
//filetit= request.getParameter("file");
System.out.println( filename );
S3Object s3obj = new S3Object("myshelf/brand/"+filename);
s3obj.setDataInputStream(filecontent);
s3Service.putObject("foofystestbucket", s3obj);
}
}
}
i think i have the problem in this part because i am using different way to connect to the database
public class Connect {
private java.sql.Connection conn=null;
public Connect () {}
public boolean dbConnect(){
boolean ok = false;
try {
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch(ClassNotFoundException ex){
ok = false;
}
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/myshelf?useServerPrepStmts=false", "myshelf", "myshelffoofysPASS");
// conn=DriverManager.getConnection("jdbc:mysql://174.129.206.66:3306/myshelf","myshelf","myshelffoofysPASS");
// conn=DriverManager.getConnection("jdbc:mysql://localhost/myshelf","root","");
ok = true;
}
catch (SQLException e) {
ok = false;
}
return ok;
}
public static Connection DbConn() throws SQLException {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// return DriverManager.getConnection("jdbc:mysql://174.129.206.66/myshelf","myshelf","myshelffoofysAPI");
//return DriverManager.getConnection("jdbc:mysql://localhost/myshelf","root","");
return DriverManager.getConnection("jdbc:mysql://localhost:3306/myshelf?useServerPrepStmts=false", "myshelf", "myshelffoofysAPI");
}
public java.sql.Connection getConn() {
return conn;
}
}

Categories

Resources